Почему моя инструкция if с backticks не работает должным образом?

Я пытаюсь создать Bash script, где пользователь сможет скопировать файл и посмотреть, успешно ли он был выполнен или нет. Но каждый раз, когда копия выполняется, правильно или нет, отображается вторая выходная "копия не была". Любая идея, как это решить?

if [ `cp -i $files $destination` ];then
        echo "Copy successful."
else
        echo "Copy was not done"
fi

Ответ 1

Вы хотите

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

Не забывайте кавычки.


Ваша версия:

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

всегда будет выполнять ветвь else.

Оператор if в командной оболочке принимает команду. Если эта команда завершается успешно (возвращает 0, которая назначается в $?), то условие выполняется успешно.

Если вы делаете if [ ... ]; then, то это то же самое, что и if test ... ; then потому что [ ] является синтаксическим сахаром для test command/builtin.

В вашем случае вы передаете результат stdout * операции cp в качестве аргумента test

Операция stdout cp будет пуста (cpобычно выводит только ошибки, а те идут в stderr). A test вызов с пустым списком аргументов является ошибкой. Ошибка приводит к ненулевому статусу выхода, и поэтому вы всегда получаете ветвь else.


* подстановка процесса $() или замена подпрограммы обратного потока slurp stdout команды, которую они запускают

Ответ 2

С обратными тиками вы проверяете вывод команды cp, а не ее статус. Здесь вам также не нужна команда тестирования (квадратные скобки).

Просто используйте:

if cp ... ; then
    ...

Ответ 3

В дополнение к проверке состояния выходных стилей, как указано в другом ответе, вы можете использовать составную команду для выполнения именно того, что вы пытаетесь, без полного синтаксиса if ... then ... else ... fi. Например:

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

Что по сути делает то же самое, что и синтаксис if. В основном:

command && 'next cmd if 1st succeeded'

и

command || 'next cmd if 1st failed'

Вы просто используете command && 'next cmd if 1st succeeded' как command в command || 'next cmd if 1st failed'. Вместе это просто:

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

Примечание. обязательно указывайте свои переменные, чтобы предотвратить расщепление слов, расширение пути и т.д.

Ответ 4

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