Як дозволити команді "cp" не створювати помилку, коли вихідний файл не існує?


59

Я використовую Mac OS X. Я намагаюся скопіювати деякі файли командою cp для сценарію збірки, як це.

cp ./src/*/*.h ./aaa

Але ця команда видає помилку, якщо в каталозі ./src немає файлу .h. Як зробити так, щоб команда не видала помилку? (тиха помилка) Помилка робить результат збірки невдалим, але я просто хочу скопіювати, коли є лише якийсь файл заголовка.

Відповіді:


69

Якщо ви говорите про повідомлення про помилку, ви можете придушити це, відправивши його у бітове відро:

cp ./src/*/*.h ./aaa 2>/dev/null

Якщо ви хочете придушити код виходу та повідомлення про помилку:

cp ./src/*/*.h ./aaa 2>/dev/null || :

8
Було б непогано пояснити, що :означає в цьому контексті.
Пьотр Доброгост

23
@PiotrDobrogost: У Баша та деяких інших оболонок товста кишка - це нульова утиліта (no-op). Це зазначено на POSIX . Оскільки він завжди повертає істину, він використовується тут для придушення вихідного коду помилки cp(якщо цього хочеться). Оболонка вбудована trueможе бути використана натомість і буде читабельнішою.
Денніс Вільямсон


1
Це також буде ігнорувати інші помилки (каталог джерела / призначення не існує, вихідний файл існує, але він не читабельний, диск наповнений, файлова система лише для читання, помилка вводу-виводу, cpне знаходяться PATHякось ...)
Володимир Пантелеев,

помилка синтаксису біля несподіваного маркера `|| '
thang

13

Ви шукаєте щось за принципом

if [ -e file ]
 then cp file /somewhere
fi

(На жаль, цей -fваріант не є дроїдом, який ви шукаєте.)

Якщо ви хочете відповідати глобусу, це не вийде; використовувати findзамість цього, наприклад:

find ./src -name \*.h -exec cp {} ./destination \;

Зауважте, що при такому підході можлива проблема TOCTOU (наприклад, якщо ви використовуєте set -e, а файл зникає між викликами [та cpвикликами, ваш сценарій вийде з ладу).
Володимир Пантелеєв

9

Старе питання, але все ще може бути актуальним для інших.
Якщо вам не потрібно використовувати cp, ви можете спробувати з rsync.
Щоб скопіювати всі файли з джерела в каталог призначення, запустіть:

rsync -avzh --ignore-errors /path/to/source /path/to/destination

Rsync постачається з більшістю Unix-подібних систем, таких як Linux, Mac OS X або FreeBSD.


4
Ви можете використовувати rsync замість cp, додавши параметр --ignore-missing-args: rsync -av --ignore-missing-args ./src/*/*.h ./aaaЦе має перевагу перед --ignore-errorsтим, що єдиними помилками, які ігноруються, є помилки, пов'язані з вихідними файлами, які не існують. З --ignore-errorsкожною помилкою ігнорується, що може бути небезпечно. Також врахуйте, що цей параметр є досить недавнім, тому він може бути відсутнім у старих версіях rsync.
jesjimher

6

Передача результату до істини гарантує, що команда завжди буде успішною. Я спробував це в Linux, але не на будь-якій Mac OS:

cp ./src/*/*.h ./aaa | true

5
Проста труба |завжди запускається, тоді як ||робиться лише в разі помилки. І, trueяк правило, є двійковим, тоді як двокрапка :є вбудованою і не споживає PID.
ott--

Баш-скрипт на MacOS - Yosemite, що містить команду "cp ./src/*/*.h ./aaa", не помиляється, якщо файлів .h не існує.
Вівек

2

Ви можете примусити правильний статус помилки. З функцією:

$ cpalways () { cp $1 $2 2>/dev/null ; return 0 ; }

З огляду на наступне:

$ ls foo bar baz
ls: baz: No such file or directory
bar foo

Регулярна копія поверне помилку. Він поверне статус виходу 1.

$ cp baz bar ; echo $?
cp: baz: No such file or directory
1

Якщо ми будемо використовувати функцію cpalways () вище, будь-які помилки будуть приховані:

$ cpalways baz bar ; echo $?
0
$ cpalways foo bar ; echo $?
0
$ cpalways baz bar ; echo $?
0
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.