Un comando como mv foo* ~/bar/produce este mensaje en stderr si no hay archivos que coincidan foo*.
mv: cannot stat `foo*': No such file or directory
Sin embargo, en el script que estoy trabajando en ese caso estaría completamente bien, y me gustaría omitir ese mensaje de nuestros registros.
¿Hay alguna buena manera de decir mvque se calle, incluso si no se movió nada?

mv foo* ~/bar/ 2> /dev/null?mv. :) Pero eso servirá, por supuesto.mvimplementaciones admiten una-qopción para silenciarlas, pero eso no es parte de la especificación POSIX paramv. EnmvGNU coreutils, por ejemplo, no tiene esa opción.Respuestas:
Estas buscando esto?
fuente
set -e(que debe usarse en cada script de shell) fallará. puede agregar a|| truepara desactivar la verificación de un solo comando.set -eno debe usarse en cada script de shell, en muchos casos hace que la gestión de errores sea aún más compleja de lo que es sin ella.En realidad, no creo que silenciar
mvsea un buen enfoque (recuerde que también podría informarle sobre otras cosas que podrían ser de interés ... por ejemplo, faltar~/bar). Desea silenciarlo solo en caso de que su expresión global no devuelva resultados. De hecho prefiero no ejecutarlo en absoluto.No se ve muy atractivo, y funciona solo en
bash.O
única excepción se encuentra en
bashlanullglobserie. Sin embargo, pagas un precio de 3 veces la repetición del patrón glob.fuente
foo*cuando es el único en el directorio actual que coincide con el globfoo*. Esto se puede solucionar con una expresión glob que no coincide literalmente, es difícil. Por ej[ 'fo[o]*' = "$(echo fo[o]*)" ] || mv fo[o]* ~/bar/.find . -maxdepth 1 -name 'foo*' -type f -print0 | xargs -0r mv -t ~/bar/- GNU
mvtiene una buena opción de "destino primero" (-t) yxargspuede omitir la ejecución de su comando si no hay ninguna entrada (-r). El uso de-print0y en-0consecuencia se asegura de que no haya un desastre cuando los nombres de archivo contienen espacios y otras cosas "divertidas".fuente
-maxdepth,-print0,-0y-rtambién son extensiones de GNU (aunque algunos de ellos se encuentran en otras implementaciones de hoy en día).mv.Es importante darse cuenta de que en realidad es el shell lo que lo expande
foo*a la lista de nombres de archivos coincidentes, por lo que pocomvpodría hacerse por sí mismo.El problema aquí es que cuando un globo no coincide, algunos shells como
bash(y la mayoría de los otros shells similares a Bourne, ese comportamiento defectuoso en realidad fue introducido por el shell Bourne a fines de los años 70) pasan el patrón textualmente al comando.Entonces, aquí, cuando
foo*no coincide con ningún archivo, en lugar de abortar el comando (como lo hacen los shells anteriores a Bourne y varios shells modernos), el shell pasa unfoo*archivo literalmv, por lo que básicamente solicitamvmover el archivo llamadofoo*.Ese archivo no existe. Si lo hiciera, en realidad habría coincidido con el patrón, por lo que
mvinforma un error. Si el patrón hubiera sido en sufoo[xy]lugar,mvpodría haber movido accidentalmente un archivo llamado enfoo[xy]lugar de los archivosfooxyfooy.Ahora, incluso en esos shells que no tienen ese problema (pre-Bourne, csh, tcsh, fish, zsh, bash -O failglob), aún obtendría un error
mv foo* ~/bar, pero esta vez por el shell.Si desea considerar que no es un error si no hay coincidencia de archivos
foo*y, en ese caso, no mover nada, primero querrá crear la lista de archivos (de una manera que no cause un error, como al usar lanullglobopción de algunos shells), y solo la llamadamves si la lista no está vacía.Eso sería mejor que ocultar todos los errores de
mv(como sumar lo2> /dev/nullharía) como simvfallara por cualquier otra razón, probablemente aún desee saber por qué.en zsh
O use una función anónima para evitar usar una variable temporal:
zshes uno de esos shells que no tienen el error Bourne e informan un error sin ejecutar el comando cuando un glob no coincide (y lanullglobopción no se ha habilitado), por lo que aquí puede ocultarzshel error y restaurar stderr formvpara que aún vea losmverrores si los hay, pero no el error sobre los globos no coincidentes:O podría usar
zargslo que también evitaría problemas si elfoo*globo se expandiera a archivos demasiado man.En ksh93:
En bash:
bashno tiene sintaxis para habilitarnullglobsolo para un globo, y lafailglobopción se cancela,nullglobpor lo que necesitaría cosas como:o configurar las opciones en una subshell para guardarlas, hay que guardarlas antes y restaurarlas después.
En
yashEn
fishEn el shell de peces, el comportamiento de nullglob es el predeterminado para el
setcomando, por lo que es solo:POSIXY
No hay ninguna
nullglobopción en POSIXshy no hay otra matriz que los parámetros posicionales. Hay un truco que puedes usar para detectar si un globo coincide o no:Mediante el uso de a
foo[*]yfoo*glob, podemos diferenciar entre el caso en el que no hay un archivo coincidente y el caso en el que hay un archivo que se llamafoo*(queset -- foo*no se pudo hacer).Más lectura:
fuente
Probablemente no sea el mejor, pero puede usar el
findcomando para verificar si la carpeta está vacía o no:fuente
foo*ruta de búsqueda literal afind.Supongo que está usando bash, porque este error depende del comportamiento de bash para expandir globos inigualables a sí mismos. (En comparación, zsh genera un error al intentar expandir un globo inigualable).
Entonces, ¿qué pasa con la siguiente solución?
Esto ignorará silenciosamente
mvsils -d foo*falla, mientras que aún registra errores sils foo*tiene éxito peromvfalla. (Tenga cuidado,ls foo*podría fallar por otras razones quefoo*no existan, por ejemplo, derechos insuficientes, problemas con el FS, etc., por lo que esta solución ignoraría tales condiciones).fuente
bash). +1 por tener en cuenta el hecho de quemvpodría fallar por otras razones quefoo*no existen.lscomando no sería muy claro para futuros lectores, al menos sin un comentario.)ls -d foo*podría regresar con un estado de salida distinto de cero por otros motivos, como después de unln -s /nowhere foobar(al menos con algunaslsimplementaciones).Puedes hacer por ejemplo
mv 1>/dev/null 2>&1 foo* ~/bar/omv foo* ~/bar/ 1&>2Para más detalles ver: http://mywiki.wooledge.org/BashFAQ/055
fuente
mv foo* ~/bar/ 1&>2no silencia el comando, envía lo que habría estado en stdout para estar también en stderr./dev/nullconNUL1y qué2significa?Puedes hacer trampa (de forma portátil) con
perl:fuente
Si va a usar Perl, también podría ir hasta el final:
o como una línea:
(Para obtener detalles del
movecomando, consulte la documentación de Archivo :: Copiar ).fuente
En lugar
tu puedes hacer
Simple, legible :)
fuente
cptampocormestán en silencio sifoo*no existe.Si el comando anterior es exitoso o no, podemos encontrar el estado de salida del comando anterior
si la salida de echo $? es distinto de 0 significa que el comando no es exitoso si la salida es 0 significa que el comando es exitoso
fuente