Sign up ×
Server Fault is a question and answer site for system and network administrators. It's 100% free, no registration required.

I am writing a BASH shell script to upload all the files in a directory to a remote server and then delete them. It'll run every few hours via a CRON job.

My complete script is below. The basic problem is that the part that's supposed to figure out whether the file uploaded successfully or not doesn't work. The SFTP command's exit status is always "0" regardless of whether the upload actually succeeded or not.

How can I figure out whether a file uploaded correctly or not so that I can know whether to delete it or let it be?


# First, save the folder path containing the files.

# Initialize a blank variable to hold messages.

# These are for notifications of file totals.

# Loop through the files.
for f in $FILES
    # Get the base filename
    BASE=`basename $f`

    # Build the SFTP command. Note space in folder name.
    CMD='cd "Destination Folder"\n'
    CMD="${CMD}put ${f}\nquit\n"

    # Execute it.
    echo -e $CMD | sftp -oIdentityFile /home/bob/.ssh/id_rsa

    # On success, make a note, then delete the local copy of the file.
    if [ $? == "0" ]; then
        MESSAGES="${MESSAGES}\tNew file: ${BASE}\n"
        (( COUNT=$COUNT+1 ))

        # Next line commented out for ease of testing
        #rm $f

    # On failure, add an error message.
    if [ $? != "0" ]; then
        ERRORS="${ERRORS}\tFailed to upload file ${BASE}\n"


SUBJECT="New Theses"

BODY="There were ${COUNT} files and ${ERRORCOUNT} errors in the latest batch.\n\n"

if [ "$MESSAGES" != "" ]; then
    BODY="${BODY}New files:\n\n${MESSAGES}\n\n"

if [ "$ERRORS" != "" ]; then
    BODY="${BODY}Problem files:\n\n${ERRORS}"

# Send a notification. 
echo -e $BODY | mail -s $SUBJECT

Due to some operational considerations that make my head hurt, I cannot use SCP. The remote server is using WinSSHD on windows, and does not have EXEC privileges, so any SCP commands fail with the message "Exec request failed on channel 0". The uploading therefore has to be done via the interactive SFTP command.

share|improve this question

4 Answers 4

up vote 1 down vote accepted

If you batch your SFTP session, the exit status $? will tell you if it's a failed transfer or not.

echo "put testfile1.txt" > batchfile.txt
sftp -b batchfile.txt user@host
if [[ $? != 0 ]]; then
  echo "Transfer failed!"
  exit 1
  echo "Transfer complete."

Edited to add: This is something we use in a production script at work, so I'm sure it's valid. We can't use scp because some of our customers are on SCO Unix.

share|improve this answer
This did the trick for me, thanks! –  Will Martin Apr 17 '12 at 14:25
I haven't done extensive testing, but I think batch mode alters how sftp exits and what exit status it presents to you. Glad that did the trick. –  UtahJarhead Apr 17 '12 at 15:01

It is the tradition of serverfault not to unduly question the preconditions, but I have to ask: is it not possible for you to either 1) mount the remote filesystem via SMB, or 2) use fuse/sshfs instead? (I assume here that the sending machine is a Linux box as you are using bash and ssh.)

To actually answer your question, I think your problem is simple. Consider:

quest@wonky:~$ false
quest@wonky:~$ if [ $? != "0" ] ; then echo asdf ; fi
quest@wonky:~$ if [ $? != "0" ] ; then echo asdf ; fi

Try instead like this:

quest@wonky:~$ false
quest@wonky:~$ res=$?
quest@wonky:~$ if [ $res != "0" ] ; then echo asdf ; fi
quest@wonky:~$ if [ $res != "0" ] ; then echo asdf ; fi

To explain: your second if statement "if [ $? != "0" ]; then" tests for the exit status of the latest statement, which is no longer sftp, but the previous if statement.

Then I wonder, will sftp really exit with non-zero if it has problems uploading files? Cursory tests indicate mine doesn't.

share|improve this answer
This is a good tip -- I didn't understand that each IF statement altered the exit status variable. So, +1, and I've adjusted my script to reflect this. But SFTP does actually exit non-zero in the script as written above -- I think because the "quit" command succeeds. Using a batch file (as in another answer) makes it generate the correct exit code, though, so between the two answers I think I've got it working. –  Will Martin Apr 17 '12 at 14:28

Use rsync(.exe) and dig in --remove-source-files & co., don´t even care about failed uploads, he will! ;-)

Yes you can tie this up with ssh, see --rsh

share|improve this answer


how about run sftp Batch script on Windows OS to detect success/failure?

I use %errorlevel% to detect success/failure, sometime the %errorlevel% be returned by 0, but that session is fail and the file is not upload to the server. my script is below

how can I detect sftp uploaded correctly? THX so much

@echo off
(echo cd %4
  echo put %2
  echo exit)>sftpScript.txt
sftp -b sftpScript.txt %3
set result=%errorlevel%
if result EQU 0 (
  del sftpScript.txt
  del %2
) else (
  del sftpScript.txt
exit %result%
share|improve this answer
Nice... first post and accepted answer! –  vgoff Nov 21 '12 at 3:21

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.