¿Cómo dejar que el comando 'cp' no active un error cuando el archivo fuente no existe?


59

Estoy usando Mac OS X. Estoy tratando de copiar algunos archivos con el comando cp para un script de compilación como este.

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

Pero este comando genera un error si no hay un archivo .h en el directorio ./src. ¿Cómo hacer que el comando no active el error? (falla silenciosa) El error hace que falle el resultado de la compilación, pero solo quiero copiar cuando solo hay algún archivo de encabezado.

Respuestas:


69

Si habla del mensaje de error, puede suprimirlo enviándolo al depósito de bits:

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

Si desea suprimir el código de salida y el mensaje de error:

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

8
Sería bueno explicar qué :significa en este contexto.
Piotr Dobrogost

23
@PiotrDobrogost: en Bash y algunas otras conchas, el colon es una utilidad nula (no-op). Está especificado por POSIX . Como siempre devuelve verdadero, se usa aquí para suprimir el código de salida de un error cp(si se desea). El shell incorporado truepodría utilizarse en su lugar y sería más legible.
Dennis Williamson


1
Esto también ignorará otros errores (el directorio fuente / destino no existe, el archivo fuente existe pero no es legible, el disco está lleno, el sistema de archivos de solo lectura, el error IO, cpno está de PATHalguna manera ...)
Vladimir Panteleev

error de sintaxis cerca del token inesperado `|| '
thang

13

Estás buscando algo en la línea de

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

(Desafortunadamente, la -fopción no es el droide que estás buscando).

Si quieres igualar un globo, eso no funcionará; utilizar finden su lugar, por ejemplo:

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

Tenga en cuenta que existe un posible problema de TOCTOU con este enfoque (por ejemplo, si lo usa set -ey el archivo desaparece entre [las cpinvocaciones y, el script se bloqueará).
Vladimir Panteleev

9

Antigua pregunta, pero aún podría ser relevante para otros.
Si no necesita usar cp, puede intentarlo con rsync.
Para copiar todos los archivos de un origen a un directorio de destino, ejecute:

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

Rsync viene con la mayoría de los sistemas tipo Unix, como Linux, Mac OS X o FreeBSD.


44
Puede usar rsync en lugar de cp, agregando el parámetro --ignore-missing-args: rsync -av --ignore-missing-args ./src/*/*.h ./aaaEsto tiene la ventaja sobre --ignore-errorsque los únicos errores ignorados son aquellos relacionados con los archivos fuente que no existen. Con --ignore-errorscada error se ignora, lo que puede ser peligroso. Además, tenga en cuenta que este parámetro es bastante reciente, por lo que podría no estar presente en las versiones anteriores de rsync.
jesjimher

6

Canalizar el resultado a verdadero asegura que el comando siempre tendrá éxito. He intentado esto en Linux pero no en ningún Mac OS:

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

55
La tubería simple |siempre se ejecuta mientras ||solo se realiza en caso de error. Y truegeneralmente es un sistema binario, mientras que el colon :está integrado y no consume un PID.
ott--

Un script bash en MacOS - Yosemite que contiene el comando "cp ./src/*/*.h ./aaa" no genera errores si los archivos .h no existen.
Vivek

2

Podría forzar el estado de error correcto. Con una función:

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

Dado lo siguiente:

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

La copia regular devolverá un error. Devolverá un estado de salida de 1.

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

Si usamos la función cpalways () anterior, se ocultarán los errores:

$ cpalways baz bar ; echo $?
0
$ cpalways foo bar ; echo $?
0
$ cpalways baz bar ; echo $?
0
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.