How can I upload (FTP) files to server in a Bash script?

BashFtp

Bash Problem Overview


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?

Bash Solutions


Solution 1 - Bash

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:

http://troy.jdmz.net/rsync/index.html

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 username@hostname.example 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 username@hostname.example

You can also use a batchfile with the -b parameter:

sftp -b batchfile.txt ~/.ssh/key_name username@hostname.example

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.

Solution 2 - Bash

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 standard input with everything up to End-Of-Session. It is a useful tip for spawning any process, not just ftp! Note that this saves spawning a separate process (echo, cat, etc.). It is not a major resource saving, but it is worth bearing in mind.

Solution 3 - Bash

The ftp command isn't designed for scripts, so controlling it is awkward, and getting its exit status is even more awkward.

Curl is made to be scriptable, and also has the merit that you can easily switch to other protocols later by just modifying the URL. If you put your FTP credentials in your .netrc, you can simply do:

# 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.

Solution 4 - Bash

Install ncftpput and ncftpget. They're usually part of the same package.

Solution 5 - Bash

The command in one line:

ftp -in -u ftp://username:password@servername/path/to/ localfile

Solution 6 - Bash

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

Solution 7 - Bash

#/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

Solution 8 - Bash

There isn't any 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...

Solution 9 - Bash

Working example to put your file on root...see, it's 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

Solution 10 - Bash

If you want to use it inside a 'for' to copy the last generated files for an everyday backup...

j=0
var="`find /backup/path/ -name 'something*' -type f -mtime -1`"
# We have some files in $var 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

Solution 11 - Bash

echo -e "open <ftp.hostname>\nuser <username> <password>\nbinary\nmkdir New_Folder\nquit" | ftp -nv

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAndrewView Question on Stackoverflow
Solution 1 - BashgregglesView Answer on Stackoverflow
Solution 2 - BashBrian AgnewView Answer on Stackoverflow
Solution 3 - BashPelle NilssonView Answer on Stackoverflow
Solution 4 - BashPaul TomblinView Answer on Stackoverflow
Solution 5 - BashChizhikView Answer on Stackoverflow
Solution 6 - BashShalView Answer on Stackoverflow
Solution 7 - BashennuikillerView Answer on Stackoverflow
Solution 8 - BashMartin HvidbergView Answer on Stackoverflow
Solution 9 - BashShalView Answer on Stackoverflow
Solution 10 - Bashoso_togariView Answer on Stackoverflow
Solution 11 - BashYavuz KaraliView Answer on Stackoverflow