Jak pozwolić komendzie „cp” nie uruchamiać błędu, gdy plik źródłowy nie istnieje?


59

Korzystam z systemu Mac OS X. Próbuję skopiować niektóre pliki za pomocą polecenia cp dla takiego skryptu kompilacji.

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

Ale to polecenie uruchamia błąd, jeśli nie ma pliku .h w katalogu ./src. Jak sprawić, by polecenie nie uruchamiało błędu? (cicha awaria) Błąd powoduje niepowodzenie kompilacji, ale chcę tylko skopiować, gdy jest tylko jakiś plik nagłówkowy.

Odpowiedzi:


69

Jeśli mówisz o komunikacie o błędzie, możesz go ukryć, wysyłając go do segmentu bitów:

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

Jeśli chcesz ukryć kod wyjścia i komunikat o błędzie:

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

8
Dobrze byłoby wyjaśnić, co :oznacza w tym kontekście.
Piotr Dobrogost

23
@PiotrDobrogost: W Bash i niektórych innych powłokach dwukropek jest narzędziem zerowym (no-op). Jest to określone przez POSIX . Ponieważ zawsze zwraca wartość true, służy tutaj do tłumienia kodu wyjścia nieudanego cp(jeśli jest to pożądane). trueZamiast tego można użyć wbudowanej powłoki i będzie ona bardziej czytelna.
Dennis Williamson


1
Zignoruje to także inne błędy (katalog źródłowy / docelowy nie istnieje, plik źródłowy istnieje, ale nie można go odczytać, dysk jest pełny, system plików tylko do odczytu, błąd we / wy, cpnie jest w PATHjakiś sposób ...)
Vladimir Panteleev

błąd składni w pobliżu nieoczekiwanego tokena `|| '
Thang

13

Szukasz czegoś w stylu

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

(Niestety -fnie jest to droid, którego szukasz).

Jeśli chcesz dopasować glob, to nie zadziała; findzamiast tego użyj np .:

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

Należy pamiętać, że istnieje potencjalny problem TOCTOU z takiego podejścia (np jeśli używasz set -e, a plik znika między [a cpinwokacje, skrypt padnie).
Vladimir Panteleev

9

Stare pytanie, ale może być nadal istotne dla innych.
Jeśli nie potrzebujesz używać cp, możesz spróbować z rsync.
Aby skopiować wszystkie pliki ze źródła do katalogu docelowego, uruchom:

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

Rsync jest dostarczany z większością systemów uniksowych, takich jak Linux, Mac OS X lub FreeBSD.


4
Możesz użyć rsync zamiast cp, dodając parametr --ignore-missing-args: rsync -av --ignore-missing-args ./src/*/*.h ./aaaMa to tę zaletę, --ignore-errorsże jedynymi ignorowanymi błędami są te związane z nieistniejącymi plikami źródłowymi. Z --ignore-errorskażdy błąd jest ignorowany, co może być niebezpieczne. Weź również pod uwagę, że ten parametr jest dość nowy, więc może nie być obecny w starych wersjach rsync.
jesjimher

6

Przesłanie wyniku do wartości true zapewnia, że ​​polecenie zawsze się powiedzie. Próbowałem tego na Linuksie, ale nie na żadnym Mac OS:

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

5
Prosta rura |jest zawsze uruchamiana, podczas gdy ||jest wykonywana tylko w przypadku błędu. I truejest zwykle dwójkowy, podczas gdy dwukropek :jest wbudowany i nie zużywa PID.
ott--

Skrypt bash na MacOS - Yosemite zawierający polecenie „cp ./src/*/*.h ./aaa” nie powoduje błędu, jeśli pliki .h nie istnieją.
Vivek

2

Możesz wymusić poprawny status błędu. Z funkcją:

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

Biorąc pod uwagę następujące kwestie:

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

Zwykła kopia zwróci błąd. Zwróci status wyjścia 1.

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

Jeśli użyjemy powyższej funkcji cpalways (), wszelkie błędy zostaną ukryte:

$ cpalways baz bar ; echo $?
0
$ cpalways foo bar ; echo $?
0
$ cpalways baz bar ; echo $?
0
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.