3

I am trying to make a Bash script where the user will be able to copy a file, and see if it was successfully done or not. But every time the copy is done, properly or not, the second output "copy was not done" is shown. Any idea how to solve this?

if [ `cp -i $files $destination` ];then
        echo "Copy successful."
else
        echo "Copy was not done"
fi
tripleee
  • 175,061
  • 34
  • 275
  • 318
Tomb_Raider_Legend
  • 431
  • 13
  • 29

4 Answers4

10

What you want is

if cp -i "$file" "$destination"; then #...

Don't forget the quotes.


You version:

if [ `cp -i $files $destination` ];then #..

will always execute the else branch.

The if statement in the shell takes a command. If that command succeeds (returns 0, which gets assigned into $?), then the condition succeeds.

If you do if [ ... ]; then, then it's the same as if test ... ; then because [ ] is syntactic sugar for the test command/builtin.

In your case, you're passing the result of the stdout* of the cp operation as an argument to test

The stdout of a cp operation will be empty (cp generally only outputs errors and those go to stderr). A test invocation with an empty argument list is an error. The error results in a nonzero exit status and thus you always get the else branch.


*the $() process substitution or the backtick process substitution slurp the stdout of the command they run

Community
  • 1
  • 1
Petr Skocik
  • 58,047
  • 6
  • 95
  • 142
5

With back ticks you are testing the output of the cp command, not its status. You also don't need the test command (square brackets) here.

Just use:

if cp ... ; then
    ...
John Hascall
  • 9,176
  • 6
  • 48
  • 72
1

In addition to testing the output verses status as correctly pointed out in the other answer, you can make use of a compound command to do exactly what your are attempting, without requiring the full if ... then ... else ... fi syntax. For example:

cp -i "$files" "$destination" && echo "Copy successful." || echo "Copy was not done"

Which essentially does the exact same thing as the if syntax. Basically:

command && 'next cmd if 1st succeeded'

and

command || 'next cmd if 1st failed'

You are simply using command && 'next cmd if 1st succeeded' as the command in command || 'next cmd if 1st failed'. Together it is simply:

command && 'next cmd if 1st succeeded' || 'next cmd if 1st failed'

Note: make sure to always quote your variables to prevent word-splitting, and pathname expansion, etc...

David C. Rankin
  • 81,885
  • 6
  • 58
  • 85
  • 1
    Just for completeness `X && Y || Z` is not actually a ternary operator in the shell. `Z` can run even if `X` succeeds (if `Y` fails). – Etan Reisner Jan 06 '16 at 03:18
0

Try:

                cp -i $files $destination
                #check return value $? if cp command was successful
                if [ "$?" == "0" ];then
                        echo "Copy successful."

                else
                        echo "Copy was not done"
                fi
VK Kashyap
  • 168
  • 1
  • 10