Considérez cette commande:
ls /mydir/*.txt | xargs chown root
L'intention est de changer les propriétaires de tous les fichiers texte en mydir
root
Le problème est que s'il n'y a pas de .txt
fichiers, mydir
xargs génère une erreur indiquant qu'aucun chemin n'est spécifié. Ceci est un exemple inoffensif car une erreur est générée, mais dans certains cas, comme dans le script que je dois utiliser ici, un chemin vide est supposé être le répertoire actuel. Donc, si j'exécute cette commande à partir de /home/tom/
là, s'il n'y a pas de résultat pour ls /mydir/*.txt
et que tous les fichiers sous /home/tom/
ont leurs propriétaires changés en root.
Alors, comment puis-je faire ignorer un résultat vide par xargs?
ls
pour une utilisation programmatique; voir mywiki.wooledge.org/ParsingLsgit branch --merged | grep -v '^* ' | xargs git branch -d
, qui échoue également sur une entrée videRéponses:
Pour GNU
xargs
, vous pouvez utiliser l' option-r
ou--no-run-if-empty
:la source
brew install findutils
.findutils
nonfileutils
.Les utilisateurs de GNU xargs non peuvent tirer profit de
-L <#lines>
,-n <#args>
,-i
et-I <string>
:Gardez à l'esprit que xargs divise la ligne en espace mais que les guillemets et les échappements sont disponibles; RTFM pour plus de détails.
De plus, comme le mentionne Doron Behar, cette solution de contournement n'est pas portable, des vérifications peuvent donc être nécessaires:
la source
xargs
ne prend pas en charge le--no-run-if-empty
commutateur et tente d'exécuter l'argument de commande sans entrée STDIN (c'est le cas dans Solaris 10). Les versions dans d'autres Unix peuvent simplement ignorer une liste vide (par exemple AIX).echo '' | xargs -n1 echo blah
ne fait rien; alorsecho 'x' | xargs -n1 echo blah
qu'imprime "bla".ls /mydir/*.txt | xargs -n 1 -I {} chown root {}
suggère cette réponse.echo '' | xargs -n1 echo blah
impressionsblah
avec GNUxargs
.man xargs
dit--no-run-if-empty
.la source
En termes de
xargs
, vous pouvez utiliser-r
comme suggéré, mais il n'est pas pris en charge par BSDxargs
.Ainsi, pour contourner le problème, vous pouvez transmettre un fichier temporaire supplémentaire, par exemple:
ou rediriger son stderr vers null (
2> /dev/null
), par exempleUne autre meilleure approche consiste à parcourir les fichiers trouvés en utilisant la
while
boucle:Voir aussi: Ignorer les résultats vides pour xargs sous Mac OS X
Veuillez également noter que votre méthode de modification des autorisations n'est pas excellente et qu'elle est déconseillée. Vous ne devriez certainement pas analyser la sortie de la
ls
commande (voir: Pourquoi vous ne devriez pas analyser la sortie de ls ). Surtout lorsque vous exécutez votre commande par root, parce que vos fichiers peuvent être constitués de caractères spéciaux qui peuvent être interprétés par le shell ou imaginer que le fichier a un caractère d'espace autour/
, alors les résultats peuvent être terribles.Par conséquent, vous devriez changer votre approche et utiliser la
find
commande à la place, par exemplela source
while IFS= read -r -d '' file
est valide. Peux-tu expliquer?Sous OSX: réimplémentation Bash de la
xargs
gestion de l'-r
argument, mettez-le par exemple$HOME/bin
et ajoutez-le auPATH
:la source
C'est un comportement de GNU xargs qui peut être supprimé en utilisant -r, --no-run-if-empty.
La variante * BSD de xargs a ce comportement par défaut, donc -r n'est pas nécessaire. Depuis FreeBSD 7.1 (sorti en janvier 2009), un argument -r est accepté (qui ne fait rien) pour des raisons de compatibilité.
Personnellement, je préfère utiliser longopts dans les scripts mais comme le * BSD xargs n'utilise pas longopts, utilisez simplement "-r" et xargs agira de la même manière sur * BSD et sur les systèmes Linux
xargs sur MacOS (actuellement MacOS Mojave) ne supporte malheureusement pas l'argument "-r".
la source