435 votes

Faire en sorte que xargs gère les noms de fichiers qui contiennent des espaces

$ ls *mp3 | xargs mplayer  

Playing Lemon.  
File not found: 'Lemon'  
Playing Tree.mp3.  
File not found: 'Tree.mp3'  

Exiting... (End of file)  

Ma commande échoue parce que le fichier "Lemon Tree.mp3" contient des espaces et donc xargs pense qu'il s'agit de deux fichiers. Puis-je faire en sorte que find + xargs fonctionnent avec des noms de fichiers comme celui-ci ?

0 votes

Au lieu de ls |grep mp3 |sed -n "7p" vous pouvez simplement utiliser echo "Lemon Tree.mp3" .

0 votes

Cette question trouve également une réponse dans stackoverflow.com/a/33528111/94687

11voto

Bendel Points 81
find . -name 'Lemon*.mp3' -print0 | xargs -­0 -i mplayer '{}' 

Cela m'a aidé dans mon cas à supprimer différents fichiers avec des espaces. Cela devrait aussi fonctionner avec mplayer. L'astuce nécessaire est les guillemets. (Testé sur Linux Xubuntu 14.04.)

10voto

shrewmouse Points 1683

Je sais que je ne réponds pas au xargs question directement mais cela vaut la peine de mentionner find 's -exec option.

Étant donné le système de fichiers suivant :

[root@localhost bokeh]# tree --charset assci bands
bands
|-- Dream\ Theater
|-- King's\ X
|-- Megadeth
`-- Rush

0 directories, 4 files

On peut faire en sorte que la commande find gère les espaces dans Dream Theater et King's X. Donc, pour trouver les batteurs de chaque groupe en utilisant grep :

[root@localhost]# find bands/ -type f -exec grep Drums {} +
bands/Dream Theater:Drums:Mike Mangini
bands/Rush:Drums: Neil Peart
bands/King's X:Drums:Jerry Gaskill
bands/Megadeth:Drums:Dirk Verbeuren

Dans le -exec option {} représente le nom du fichier, y compris le chemin d'accès. Notez que vous n'avez pas besoin de l'échapper ou de le mettre entre guillemets.

La différence entre -exec Les terminaisons de l'utilisateur ( + y \; ) est que + regroupe autant de noms de fichiers qu'il peut sur une seule ligne de commande. Alors que \; exécutera la commande pour chaque nom de fichier.

Donc, find bands/ -type f -exec grep Drums {} + aura pour résultat :

grep Drums "bands/Dream Theater" "bands/Rush" "bands/King's X" "bands/Megadeth"

y find bands/ -type f -exec grep Drums {} \; aura pour résultat :

grep Drums "bands/Dream Theater"
grep Drums "bands/Rush"
grep Drums "bands/King's X"
grep Drums "bands/Megadeth"

Dans le cas de grep cela a pour effet secondaire d'imprimer ou non le nom du fichier.

[root@localhost bokeh]# find bands/ -type f -exec grep Drums {} \;
Drums:Mike Mangini
Drums: Neil Peart
Drums:Jerry Gaskill
Drums:Dirk Verbeuren

[root@localhost bokeh]# find bands/ -type f -exec grep Drums {} +
bands/Dream Theater:Drums:Mike Mangini
bands/Rush:Drums: Neil Peart
bands/King's X:Drums:Jerry Gaskill
bands/Megadeth:Drums:Dirk Verbeuren

Bien sûr, grep Options de l'UE -h y -H contrôlera si le nom du fichier est imprimé ou non, quelle que soit la façon dont l'option grep s'appelle.


xargs

xargs peut également contrôler la façon dont les fichiers de manuel se trouvent sur la ligne de commande.

xargs regroupe par défaut tous les arguments sur une seule ligne. Afin de faire la même chose que -exec \; utilise xargs -l . Notez que le -t L'option indique xargs pour imprimer la commande avant de l'exécuter.

[root@localhost bokeh]# find ./bands -type f  | xargs -d '\n' -l -t grep Drums
grep Drums ./bands/Dream Theater 
Drums:Mike Mangini
grep Drums ./bands/Rush 
Drums: Neil Peart
grep Drums ./bands/King's X 
Drums:Jerry Gaskill
grep Drums ./bands/Megadeth 
Drums:Dirk Verbeuren

Voyez que le -l L'option indique à xargs d'exécuter grep pour chaque nom de fichier.

Par rapport à la valeur par défaut (c'est-à-dire aucune -l option) :

[root@localhost bokeh]# find ./bands -type f  | xargs -d '\n'  -t grep Drums
grep Drums ./bands/Dream Theater ./bands/Rush ./bands/King's X ./bands/Megadeth 
./bands/Dream Theater:Drums:Mike Mangini
./bands/Rush:Drums: Neil Peart
./bands/King's X:Drums:Jerry Gaskill
./bands/Megadeth:Drums:Dirk Verbeuren

xargs a un meilleur contrôle sur le nombre de fichiers pouvant se trouver sur la ligne de commande. Donnez à la -l option le nombre maximum de fichiers par commande.

[root@localhost bokeh]# find ./bands -type f  | xargs -d '\n'  -l2 -t grep Drums
grep Drums ./bands/Dream Theater ./bands/Rush 
./bands/Dream Theater:Drums:Mike Mangini
./bands/Rush:Drums: Neil Peart
grep Drums ./bands/King's X ./bands/Megadeth 
./bands/King's X:Drums:Jerry Gaskill
./bands/Megadeth:Drums:Dirk Verbeuren
[root@localhost bokeh]# 

Voir que grep a été exécuté avec deux noms de fichiers à cause de -l2 .

5voto

Byron Formwalt Points 41

Sous macOS 10.12.x (Sierra), si vous avez des espaces dans les noms de fichiers ou les sous-répertoires, vous pouvez utiliser ce qui suit :

find . -name '*.swift' -exec echo '"{}"' \; |xargs wc -l

4voto

A-B-B Points 797

ls | grep mp3 | sed -n "7p" | xargs -i mplayer {}

Notez que dans la commande ci-dessus, xargs appellera mplayer à nouveau pour chaque dossier. Cela peut être indésirable pour mplayer mais peut convenir à d'autres cibles.

1 votes

Un complément utile aux réponses existantes, mais il convient de noter que cela entraînera mplayer à être appelé à nouveau pour chaque fichier. Cela importe si vous essayez, par exemple, de ... | xargs -I{} mplayer -shuffle {} : le jeu se déroulera dans un ordre complètement déterministe, malgré -shuffle .

1 votes

Ce n'est généralement pas l'intention. xargs est principalement utilisé avec les commandes qui acceptent une liste de noms de fichiers (exemple facile : rm ), et essaie de passer autant de noms de fichiers que possible dans chaque invocation, ne se séparant en plusieurs invocations que si nécessaire. Vous pouvez voir la différence lorsque vous utilisez une commande où chaque invocation est visible, telle que echo (par défaut) : seq 0 100000 | xargs imprime tous les nombres de 0 à 23695 (selon la plate-forme, mais c'est ce qui se passe sur mon système) sur la première ligne, jusqu'à 45539 sur la ligne 2, etc. Et vous avez raison, pour la plupart des commandes, cela n'a pas d'importance.

3voto

Charlie Dalsass Points 187

Les solutions alternatives peuvent être utiles...

Vous pouvez également ajouter un caractère nul à la fin de vos lignes en utilisant Perl, puis utiliser la commande -0 dans xargs. Contrairement à l'option xargs -d ' \n ' (dans la réponse approuvée) - cela fonctionne partout, y compris sous OS X.

Par exemple, pour lister récursivement (exécuter, déplacer, etc.) des fichiers MPEG3 qui peuvent contenir des espaces ou d'autres caractères bizarres - j'utiliserais :

find . | grep \.mp3 | perl -ne 'chop; print "$_\0"' | xargs -0  ls

(Note : Pour le filtrage, je préfère la syntaxe "| grep", plus facile à mémoriser, aux arguments --name de "find").

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X