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 mv
que se calle, incluso si no se movió nada?
mv foo* ~/bar/ 2> /dev/null
?mv
. :) Pero eso servirá, por supuesto.mv
implementaciones admiten una-q
opción para silenciarlas, pero eso no es parte de la especificación POSIX paramv
. Enmv
GNU 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|| true
para desactivar la verificación de un solo comando.set -e
no 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
mv
sea 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
bash
lanullglob
serie. 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
mv
tiene una buena opción de "destino primero" (-t
) yxargs
puede omitir la ejecución de su comando si no hay ninguna entrada (-r
). El uso de-print0
y en-0
consecuencia se asegura de que no haya un desastre cuando los nombres de archivo contienen espacios y otras cosas "divertidas".fuente
-maxdepth
,-print0
,-0
y-r
tambié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 pocomv
podrí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 solicitamv
mover el archivo llamadofoo*
.Ese archivo no existe. Si lo hiciera, en realidad habría coincidido con el patrón, por lo que
mv
informa un error. Si el patrón hubiera sido en sufoo[xy]
lugar,mv
podría haber movido accidentalmente un archivo llamado enfoo[xy]
lugar de los archivosfoox
yfooy
.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 lanullglob
opción de algunos shells), y solo la llamadamv
es si la lista no está vacía.Eso sería mejor que ocultar todos los errores de
mv
(como sumar lo2> /dev/null
haría) como simv
fallara 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:
zsh
es uno de esos shells que no tienen el error Bourne e informan un error sin ejecutar el comando cuando un glob no coincide (y lanullglob
opción no se ha habilitado), por lo que aquí puede ocultarzsh
el error y restaurar stderr formv
para que aún vea losmv
errores si los hay, pero no el error sobre los globos no coincidentes:O podría usar
zargs
lo que también evitaría problemas si elfoo*
globo se expandiera a archivos demasiado man.En ksh93:
En bash:
bash
no tiene sintaxis para habilitarnullglob
solo para un globo, y lafailglob
opción se cancela,nullglob
por lo que necesitaría cosas como:o configurar las opciones en una subshell para guardarlas, hay que guardarlas antes y restaurarlas después.
En
yash
En
fish
En el shell de peces, el comportamiento de nullglob es el predeterminado para el
set
comando, por lo que es solo:POSIXY
No hay ninguna
nullglob
opción en POSIXsh
y 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
find
comando 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
mv
sils -d foo*
falla, mientras que aún registra errores sils foo*
tiene éxito peromv
falla. (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 quemv
podría fallar por otras razones quefoo*
no existen.ls
comando 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 algunasls
implementaciones).Puedes hacer por ejemplo
mv 1>/dev/null 2>&1 foo* ~/bar/
omv foo* ~/bar/ 1&>2
Para más detalles ver: http://mywiki.wooledge.org/BashFAQ/055
fuente
mv foo* ~/bar/ 1&>2
no silencia el comando, envía lo que habría estado en stdout para estar también en stderr./dev/null
conNUL
1
y qué2
significa?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
move
comando, consulte la documentación de Archivo :: Copiar ).fuente
En lugar
tu puedes hacer
Simple, legible :)
fuente
cp
tampocorm
está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