Come consentire al comando 'cp' di non generare un errore quando il file sorgente non esiste?


59

Sto usando Mac OS X. Sto cercando di copiare alcuni file con il comando cp per uno script di compilazione come questo.

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

Ma questo comando genera un errore se non è presente alcun file .h nella directory ./src. Come fare il comando non sparare l'errore? (errore silenzioso) L'errore fa fallire il risultato della compilazione, ma voglio solo copiarlo quando ci sono solo file di intestazione.

Risposte:


69

Se stai parlando del messaggio di errore, puoi eliminarlo inviandolo al bucket bit:

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

Se si desidera eliminare il codice di uscita e il messaggio di errore:

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

8
Sarebbe bello spiegare cosa :significhi in questo contesto.
Piotr Dobrogost,

23
@PiotrDobrogost: in Bash e in alcune altre shell i due punti sono un'utilità nulla (no-op). È specificato da POSIX . Poiché restituisce sempre true, viene utilizzato qui per sopprimere il codice di uscita di un errore cp(se lo si desidera). Al suo trueposto è possibile utilizzare la shell incorporata e sarebbe più leggibile.
Dennis Williamson,


1
Ciò ignorerà anche altri errori (la directory di origine / destinazione non esiste, il file di origine esiste ma non è leggibile, il disco è pieno, il file system di sola lettura, l'errore IO, cpnon essendo in PATHqualche modo ...)
Vladimir Panteleev

errore di sintassi vicino token imprevisto `|| '
Grazie

13

Stai cercando qualcosa sulla falsariga di

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

(Sfortunatamente, l' -fopzione non è il droide che stai cercando.)

Se vuoi abbinare un glob, non funzionerà; utilizzare findinvece, ad esempio:

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

Si noti che esiste un potenziale problema TOCTOU con tale approccio (ad esempio se si utilizza set -ee il file scompare tra [le cpinvocazioni e, lo script si arresterà in modo anomalo).
Vladimir Panteleev,

9

Vecchia domanda, ma potrebbe comunque essere rilevante per gli altri.
Se non hai bisogno di usare cp, puoi provare con rsync.
Per copiare tutti i file da un'origine a una directory di destinazione, eseguire:

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

Rsync viene fornito con la maggior parte dei sistemi simili a Unix come Linux, Mac OS X o FreeBSD.


4
È possibile utilizzare rsync anziché cp, aggiungendo il parametro --ignore-missing-args: rsync -av --ignore-missing-args ./src/*/*.h ./aaaquesto ha il vantaggio --ignore-errorsche gli unici errori ignorati sono quelli relativi ai file di origine inesistenti. Con --ignore-errorsogni errore viene ignorato, il che può essere pericoloso. Inoltre, tieni presente che questo parametro è abbastanza recente, quindi potrebbe non essere presente nelle vecchie versioni di rsync.
jesjimher,

6

Il piping del risultato su true garantisce che il comando abbia sempre esito positivo. Ho provato questo su Linux ma non su alcun Mac OS:

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

5
La semplice pipe |viene sempre eseguita mentre ||viene eseguita solo in caso di errore. Di truesolito è un file binario mentre i due punti :sono integrati e non consumano un PID.
ott--

Uno script bash su MacOS - Yosemite contenente il comando "cp ./src/*/*.h ./aaa" non genera errori se i file .h non esistono.
Vivek,

2

È possibile forzare lo stato di errore corretto. Con una funzione:

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

Dato quanto segue:

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

La copia normale restituirà un errore. Restituirà uno stato di uscita di 1.

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

Se utilizziamo la funzione cpalways () sopra, eventuali errori verranno nascosti:

$ cpalways baz bar ; echo $?
0
$ cpalways foo bar ; echo $?
0
$ cpalways baz bar ; echo $?
0
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.