How to run an sftp subcommand with a bash script?

Viewed 611

I am trying to send a file to my phone using the SFTP protocol in my home network. Though I can easily send the file to my phone using the put command in FTP, but I want to automate the task. So I wrote this script:

#! /bin/bash
#Capture and share screenshot to my phone
gnome-screenshot
cd /home/prm/Pictures
FILE="$(ls -Art | tail -n 1)" #To get the last created file
sftp sftp://192.168.1.2:1753/primary/DCIM/Screenshots
put /home/prm/Pictures/$FILE

I am able to connect to my phone and required directory, but I don't how to upload. Please help!

After updating the code to:

#! /bin/bash
#Capture and share screenshot to my phone
gnome-screenshot
cd /home/prm/Pictures
FILE="$(ls -Art | tail -n 1)" #To get the last created file
echo $FILE
sftp sftp://192.168.1.3:1761/primary/DCIM/Screenshots -b <<<"put /home/prm/Pictures/$FILE"

I got the following output:

prm@prm-2018-02:~/Documents/Anubhav/Bash$ ./capture.sh
Screenshot from 2020-06-04 22-38-27.png
Connected to 192.168.1.3.
Fetching /primary/DCIM/Screenshots/ to -b/Screenshots
Cannot download non-regular file: /primary/DCIM/Screenshots/

I also tried adding -r flag:

sftp -r sftp://192.168.1.3:1761/primary/DCIM/Screenshots -b <<<"put /home/prm/Pictures/$FILE"

But this copied screenshots from my phone to the local system.

prm@prm-2018-02:~/Documents/Anubhav/Bash$ ./capture.sh
Screenshot from 2020-06-04 22-51-51.png
Connected to 192.168.1.3.
Fetching /primary/DCIM/Screenshots/ to -b/Screenshots
Retrieving /primary/DCIM/Screenshots
/primary/DCIM/Screenshots/Screenshot_20200604-225146.jpg                                        100%  176KB 549.6KB/s   00:00   
2 Answers

The put /home/prm/Pictures/$FILE command is "executed" by the shell, and you want it to be executed by the sftp command.

sftp has support for batch files using -b.Something like this should do the trick:

[sorin@localhost ~]$ sftp -b- sftp://test/ <<< "put $FILE"
Connected to test.
sftp> put test.txt
Uploading test.txt to /home/sorin/test.txt
test.txt                                                  100%    0     0.0KB/s   00:00

Note that -b requires non-interactive authentication, any prompt will get stuck.

Note: previous variant sftp sftp://test/ -b<<< "put $FILE" was wrong!The -b was ignored, options should precede the connection string. It seemed to work because sftp checks if the stdin is a terminal and handles that case correctly.

However there are some issues: in batch mode, sftp terminates on first error and sets a non-zero exit code, in "interactive mode" it ignores errors, so you can't do any error handling.

[sorin@localhost ~]$ sftp sftp://test/ -b<<<"put fkdkd
put test.txt"
Connected to test.
sftp> put fkdkd
stat fkdkd: No such file or directory
sftp> put test.txt
Uploading test.txt to /home/sorin/test.txt
test.txt                                      100%    0     0.0KB/s   00:00    
[sorin@localhost ~]$ echo $?
0
[sorin@localhost ~]$ sftp -b- sftp://test/ <<<"put fkdkd
put test.txt"
sftp> put fkdkd
stat fkdkd: No such file or directory
[sorin@localhost ~]$ echo $?
1
[sorin@localhost ~]$ 

Thanks Sorin, you brought me closer to solution, and finally this solved.

#! /bin/bash
#Capture and share screenshot to my phone
gnome-screenshot
cd /home/prm/Pictures
FILE="$(ls -Art | tail -n 1)" #To get the last created file
echo $FILE
sftp sftp://192.168.1.3:1761/primary/DCIM/Screenshots <<EOF
put "$FILE"
bye
EOF
Related