Considere este comando:
ls /mydir/*.txt | xargs chown root
La intención es cambiar los propietarios de todos los archivos de texto mydir
a raíz
El problema es que si no hay .txt
archivos en mydir
xargs, aparece un error que indica que no hay una ruta especificada. Este es un ejemplo inofensivo porque se está generando un error, pero en algunos casos, como en el script que necesito usar aquí, se supone que una ruta en blanco es el directorio actual. Entonces, si ejecuto ese comando desde /home/tom/
entonces, si no hay ningún resultado ls /mydir/*.txt
y todos los archivos bajo /home/tom/
tienen sus propietarios cambiados a root.
Entonces, ¿cómo puedo hacer que xargs ignore un resultado vacío?
ls
para uso programático; ver mywiki.wooledge.org/ParsingLsgit branch --merged | grep -v '^* ' | xargs git branch -d
, que también falla en la entrada vacíaRespuestas:
Para GNU
xargs
, puede usar la opción-r
o--no-run-if-empty
:fuente
brew install findutils
.findutils
, Nofileutils
.Los usuarios de GNU xargs no pueden hacer uso de
-L <#lines>
,-n <#args>
,-i
, y-I <string>
:Tenga en cuenta que xargs divide la línea en el espacio en blanco, pero hay comillas y escapes disponibles; RTFM para más detalles.
Además, como menciona Doron Behar, esta solución no es portátil, por lo que es posible que se necesiten controles:
fuente
xargs
no admite el--no-run-if-empty
conmutador e intenta ejecutar el argumento del comando sin entrada STDIN (este es el caso en Solaris 10). Las versiones en otros unixes pueden ignorar una lista vacía (por ejemplo, AIX).echo '' | xargs -n1 echo blah
no hace nada; mientras queecho 'x' | xargs -n1 echo blah
imprime "bla".ls /mydir/*.txt | xargs -n 1 -I {} chown root {}
como sugiere esta respuesta.echo '' | xargs -n1 echo blah
imprimeblah
con GNU'sxargs
.man xargs
dice--no-run-if-empty
.fuente
En términos de
xargs
, puede usar-r
como se sugiere, sin embargo, BSD no lo admitexargs
.Entonces, como solución alternativa, puede pasar algún archivo temporal adicional, por ejemplo:
o redirigir su stderr a nulo (
2> /dev/null
), por ejemploOtro mejor enfoque es iterar sobre los archivos encontrados usando el
while
bucle:Consulte también: Ignorar resultados vacíos para xargs en Mac OS X
También tenga en cuenta que su método para cambiar los permisos no es excelente y se desaconseja. Definitivamente no debe analizar la salida del
ls
comando (consulte: Por qué no debe analizar la salida de ls ). Especialmente cuando está ejecutando su comando por root, porque sus archivos pueden consistir en caracteres especiales que pueden ser interpretados por el shell o imaginar que el archivo tiene un carácter de espacio alrededor/
, entonces los resultados pueden ser terribles.Por lo tanto, debe cambiar su enfoque y usar el
find
comando en su lugar, por ejemplofuente
while IFS= read -r -d '' file
es válido. ¿Puedes explicar?En OSX: reimplementación de Bash para
xargs
tratar el-r
argumento, póngalo, por ejemplo,$HOME/bin
y agréguelo aPATH
:fuente
Este es un comportamiento de GNU xargs que puede suprimirse mediante el uso de -r, --no-run-if-empty.
La variante * BSD de xargs tiene este comportamiento predeterminado, por lo que no se necesita -r. Desde FreeBSD 7.1 (lanzado en enero de 2009) se acepta un argumento -r (que no hace nada) por razones de compatibilidad.
Personalmente prefiero usar longopts en scripts, pero dado que * BSD xargs no usa longopts, solo use "-r" y xargs actuará de la misma manera en * BSD y en sistemas Linux
xargs en MacOS (actualmente MacOS Mojave) lamentablemente no admite el argumento "-r".
fuente