How to upload (FTP) files to server in a bash script?
I'm trying to write a bash script that uploads a file to a server. How can I achieve this? Is a bash script the right thing to use for this?
Below are two answers. First is a suggestion to use a more secure/flexible solution like ssh/scp/sftp. Second is an explanation of how to run ftp in batch mode.
A secure solution:
You really should use SSH/SCP/SFTP for this rather than FTP. SSH/SCP have the benefits of being more secure and working with public/private keys which allows it to run without a username or password.
You can send a single file:
scp <file to upload> <username>@<hostname>:<destination path>
Or a whole directory:
scp -r <directory to upload> <username>@<hostname>:<destination path>
For more details on setting up keys and moving files to the server with RSYNC, which is useful if you have a lot of files to move, or if you sometimes get just one new file among a set of random files, take a look at:
You can also execute a single command after sshing into a server:
From man ssh
ssh [...snipped...] hostname [command] If command is specified, it is executed on the remote host instead of a login shell.
So, an example command is:
ssh firstname.lastname@example.org bunzip file_just_sent.bz2
If you can use SFTP with keys to gain the benefit of a secured connection, there are two tricks I've used to execute commands.
First, you can pass commands using echo and pipe
echo "put files*.xml" | sftp -p -i ~/.ssh/key_name email@example.com
You can also use a batchfile with the -b parameter:
sftp -b batchfile.txt ~/.ssh/key_name firstname.lastname@example.org
An FTP solution, if you really need it:
If you understand that FTP is insecure and more limited and you really really want to script it...
There's a great article on this at http://www.stratigery.com/scripting.ftp.html
#!/bin/sh HOST='ftp.example.com' USER='yourid' PASSWD='yourpw' FILE='file.txt' ftp -n $HOST <<END_SCRIPT quote USER $USER quote PASS $PASSWD binary put $FILE quit END_SCRIPT exit 0
The "-n" to ftp ensures that the command won't try to get the password from the current terminal. The other fancy part is the use of a heredoc: the <<END_SCRIPT starts the heredoc and then that exact same END_SCRIPT on the beginning of the line by itself ends the heredoc. The binary command will set it to binary mode which helps if you are transferring something other than a text file.
You can use a heredoc to do this e.g.
ftp -n $Server <<End-Of-Session # -n option disables auto-logon user anonymous "$Password" binary cd $Directory put "$Filename.lsm" put "$Filename.tar.gz" bye End-Of-Session
so the ftp process is fed on stdin with everything up to End-Of-Session. A useful tip for spawning any process, not just ftp! Note that this saves spawning a separate process (echo, cat etc.). Not a major resource saving, but worth bearing in mind.
Install ncftpput and ncftpget. They're usually part of the same package.
command in one line:
ftp -in -u ftp://username:password@servername/path/to/ localfile
use this to upload a file to a remote location
#!/bin/bash #$1 is the file name #usage:this_script <filename> HOST='your host' USER="your user" PASSWD="pass" FILE="abc.php" REMOTEPATH='/html' ftp -n $HOST <<END_SCRIPT quote USER $USER quote PASS $PASSWD cd $REMOTEPATH put $FILE quit END_SCRIPT exit 0
#/bin/bash # $1 is the file name # usage: this_script <filename> IP_address="xx.xxx.xx.xx" username="username" domain=my.ftp.domain password=password echo " verbose open $IP_address USER $username $password put $1 bye " | ftp -n > ftp_$$.log
No need to complicate stuff - this should work:
#/bin/bash echo " verbose open ftp.mydomain.net user myusername mypassword ascii put textfile1 put textfile2 bin put binaryfile1 put binaryfile2 bye " | ftp -n > ftp_$$.log
or you can use mput if you have many files ...
Working Example to Put Your File on Root ...........see its very simple
#!/bin/sh HOST='ftp.users.qwest.net' USER='yourid' PASSWD='yourpw' FILE='file.txt' ftp -n $HOST <<END_SCRIPT quote USER $USER quote PASS $PASSWD put $FILE quit END_SCRIPT exit 0
cd C:\Program Files (x86)\WinSCP
winscp.exe /console /command "open UserName:**@Server" "put File path"
if you want to use it inside a 'for' to copy the last generated files for a every-day bacakup...
j=0 var="`find /backup/path/ -name 'something*' -type f -mtime -1`" #we have in $var some files with last day change date for i in $var do j=$(( $j + 1 )) dirname="`dirname $i`" filename="`basename $i`" /usr/bin/ftp -in >> /tmp/ftp.good 2>> /tmp/ftp.bad << EOF open 123.456.789.012 user user_name passwd bin lcd $dirname put $filename quit EOF #end of ftp done #end of for iteration
The ftp command isn't designed for scripts, so controlling it is awkward, and getting its exit status is even more awkward.
# Download file curl --netrc --remote-name ftp://ftp.example.com/file.bin # Upload file curl --netrc --upload-file file.bin ftp://ftp.example.com/
If you must, you can specify username and password directly on the command line using --user username:password instead of --netrc.
echo -e "open <ftp.hostname>\nuser <username> <password>\nbinary\nmkdir New_Folder\nquit"|ftp -nv