1

I have the following code ..

while read copy
do
  cp -v $copy | tee -a $LOGFILE
  echo $?
    if [[ $? -ne 0 ]]
      then
        echo "Error copying files. Exiting ..." | tee -a $LOGFILE
        exit 1
    fi

done < copy_new_files.tmp

.. and I would like the script to halt if a file cant be copied for an error such as permission denied.

The output from the script isn't producing an error code on the permission denied error ..

+ read copy
+ cp -v acts035.fmt /home/test/gp/efin/source/pl/acts035.fmt
cp: cannot create regular file `/home/test/gp/efin/source/pl/acts035.fmt': Permission denied
+ tee -a /home/test/gp/efin/fixes/12345/efin_fix_copy_12345.log
`acts035.fmt' -> `/home/test/gp/efin/source/pl/acts035.fmt'
+ echo 0
0

How can I get the script to pause if there is an error ?

Many thanks.

6
  • This Permission denied suggests you have no rights to write in the log file. Commented Jun 16, 2014 at 11:41
  • 1
    Using $? twice looks suspicious. echo $? changes it. Maybe you should store the value before using it. Commented Jun 16, 2014 at 11:46
  • 1
    if you need to pause in an interactive mode it's enough to write instead of exit 1 a line like read ppppp. And press return when you want to go forward Commented Jun 16, 2014 at 11:51
  • please post some lines from copy_new_files.tmp. Commented Jun 16, 2014 at 12:07
  • The script you posted did not produce the error messages you posted. The script you posted would have cp complaining about not having enough arguments - it requires at least two, and you have only given it one. Commented Jun 16, 2014 at 14:44

1 Answer 1

3

Some little insidious things, I hope to be not overlong:

  • A first problem was that $? returns the last exit error code.
    So when you execute echo $? in the following line, you set $? to a new value, 0 in this case: I see no reason for which the echo command have to fail.

  • A second more insidious problem was that the precedent command is a pipe. So the variable to be used is ${PIPESTATUS[0]} and not $?. (There is [0] because it is an array and we want the value stored in the 1st component that is the exit status of the 1st command).
    Once again you can store in a variable this value or you can execute immediately after the test. Otherwise the use of other commands will reset again the variable values.

  • To pause the execution of the script it should enough to write an input line like read -p x < /dev/tty. To be insidious this time is the standard input flushing that we overcame asking input from tty.

  • It is generally safer to use read -r than read.

    -r raw input - disables interpretation of backslash escapes and line-continuation in the read data

so a code variant should be:

while read -r copy
do
  cp -v $copy  |  tee -a $LOGFILE
  # echo $? ${PIPESTATUS[0]}              # NOT HERE  else you loose it
    if [[ ${PIPESTATUS[0]} -ne 0 ]]       # $? was referred to the last command. 
      then                                # Use ${PIPESTATUS[0]} instead
        echo "Error copying files. ${copy}  Exiting ..." | tee -a $LOGFILE
                                          # It will wait that you press return
        read -p "Press CTRL-C to interrupt, RETURN to continue " x < /dev/tty 
        # exit 1                          # It will not exit: (#) means comment.
    fi
done < copy_new_files.tmp

Note: as suggested by chepner The issue with capturing the exit status of cp can also be fixed by piping the standard output of the while loop to a single call to tee, rather than the cp and the echo individually, that is even more elegant. Of course in that case you will write in the output file all the text printed in the cycle while, and even the not needed "Press CTRL-C to interrupt, RETURN to continue " lines I added.

Sign up to request clarification or add additional context in comments.

3 Comments

Dont need the "aaaaa". read already has a default variable $REPLY, so if you're not using the variable might as well just write read
Thanks, it's right like the sun shines :-). My purpose was to keep that value to skip the pause or to exit directly the next time that an error is found. There are another couple of things to fix, I'm waiting he posts some lines of the source file.
The issue with capturing the exit status of cp can also be fixed by piping the standard output of the while loop to a single call to tee, rather than the cp and the echo individually.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.