Comment ignorer xargs commandes si stdin d'entrée est vide?
Considérer cette commande:
ls /mydir/*.txt | xargs chown root
L'intention est de changer de propriétaire de tous les fichiers texte dans mydir
à la racine
Le problème est que si il n'y a pas .txt
fichiers dans mydir
puis xargs thows une erreur disant qu'il y a pas de chemin d'accès spécifié. C'est un inoffensif exemple parce qu'une erreur est levée, mais dans certains cas, comme dans le script que j'ai besoin d'utiliser ici, un chemin vide est supposé être le répertoire courant. Donc, si je exécuter cette commande à partir de /home/tom/
puis si il n'y a pas de résultat pour ls /mydir/*.txt
et tous les fichiers sous /home/tom/
leurs propriétaires changé à la racine.
Alors, comment puis-je avoir xargs ignorer un résultat vide?
- Aparté: ne Jamais sortie de tuyau de
ls
pour une utilisation par programmation; voir mywiki.wooledge.org/ParsingLs
Vous devez vous connecter pour publier un commentaire.
Pour GNU
xargs
, vous pouvez utiliser le-r
ou--no-run-if-empty
option:brew install findutils
.findutils
, pasfileutils
.Utilisateurs de non-GNU xargs peut prendre avantage de
-L <#lines>
,-n <#args>
,-i
, et-I <string>
:Gardez à l'esprit que xargs divise la ligne à l'espace, mais en les citant et d'échappement sont disponibles; RTFM pour plus de détails.
Aussi, comme Doron Behar mentionne, cette solution de contournement n'est pas portable, des contrôles peuvent être nécessaires:
xargs
ne prend pas en charge la--no-run-if-empty
interrupteur et tente d'exécuter la commande argument sans STDIN d'entrée (c'est le cas dans Solaris 10). Les versions dans les autres systèmes unix peut simplement ignorer une liste vide (par exemple, AIX).echo '' | xargs -n1 echo blah
ne fait rien; queecho 'x' | xargs -n1 echo blah
imprime "bla".ls /mydir/*.txt | xargs -n 1 -I {} chown root {}
, que cette réponse suggère.-i
impliquent déjà-n 1
depuis qu'ils se substituer l'un argument par l'emplacement réservé. Aussi votre espace réservé peut être n'importe quelle chaîne (après coquille de traitement);{}
est juste la valeur par défaut pour-i
.ls /mydir/*.txt | xargs -n 1 chown root {}
echo '' | xargs -n1 echo blah
imprimeblah
avec GNUxargs
.man xargs
dit--no-run-if-empty
.En termes de
xargs
, vous pouvez utiliser-r
comme l'a suggéré, cependant, il n'est pas pris en charge par BSDxargs
.Donc, comme solution de contournement, vous pouvez passer quelques extra fichier temporaire, par exemple:
ou réorienter ses stderr vers null (
2> /dev/null
), par exempleUne autre meilleure approche est d'itérer sur les fichiers trouvés à l'aide de
while
boucle:Voir aussi: Ignorer vide résultats pour xargs dans Mac OS X
Aussi, veuillez noter que votre méthode de modification des autorisations n'est pas grand et il est découragé. Certainement vous ne devriez pas analyser la sortie de
ls
commande (voir: Pourquoi vous ne devriez pas analyser la sortie de ls). Surtout quand vous êtes en cours d'exécution de votre commande en root, car vos fichiers peuvent consister en des caractères spéciaux qui peuvent être interprétés par le shell ou d'imaginer les fichier ayant un caractère d'espace autour de/
, alors les résultats peuvent être terribles.Par conséquent, vous devriez changer votre approche et l'utilisation
find
de commande au lieu de cela, par exemple,while IFS= read -r -d '' file
est valide. Pouvez-vous expliquer?Sur OSX: Bash la remise à plat de
xargs
traiter avec la-r
argument, mettre par exemple dans$HOME/bin
et l'ajouter à laPATH
:C'est un comportement de GNU xargs qui peut être supprimé en utilisant l'option-r, --no-run-si-vide.
Les *BSD variante de xargs a ce comportement sur défaut, donc -r n'est pas nécessaire. Depuis FreeBSD 7.1 (sorti en janvier 2009) l'argument-r est accepté (sorcière ne fait rien) pour des raisons de compatibilité.
Personnellement, je préfère utiliser des longopts dans des scripts, mais depuis les *BSD xargs n'utilise longopts suffit d'utiliser "-r" et xargs agiront de même sur *BSD sur les systèmes linux
xargs sur MacOS (actuellement MacOS Mojave) malheureusement ne supporte pas l'argument "-r".