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

3voto

Jonathan Leffler Points 299946

Cela dépend (a) de l'attachement que vous portez au chiffre 7 par rapport à, disons, Lemons, et (b) du fait que certains de vos noms de fichiers contiennent ou non des retours à la ligne (et si vous êtes prêt à les renommer si c'est le cas).

Il y a de nombreuses façons d'y faire face, mais certaines d'entre elles sont :

mplayer Lemon*.mp3

find . -name 'Lemon*.mp3' -exec mplayer {} ';'

i=0
for mp3 in *.mp3
do
    i=$((i+1))
    [ $i = 7 ] && mplayer "$mp3"
done

for mp3 in *.mp3
do
    case "$mp3" in
    (Lemon*) mplayer "$mp3";;
    esac
done

i=0
find . -name *.mp3 |
while read mp3
do
    i=$((i+1))
    [ $i = 7 ] && mplayer "$mp3"
done

Le site read ne fonctionne pas si les noms de fichiers contiennent des nouvelles lignes ; les autres fonctionnent correctement même avec des nouvelles lignes dans les noms (sans parler des espaces). À mon avis, si vos noms de fichiers contiennent une ligne de retour, vous devriez renommer le fichier sans la ligne de retour. L'utilisation des guillemets doubles autour du nom du fichier est la clé du bon fonctionnement des boucles.

Si vous avez GNU find et GNU xargs (ou FreeBSD (*BSD ?), ou Mac OS X), vous pouvez également utiliser la fonction -print0 y -0 options, comme dans :

find . -name 'Lemon*.mp3' -print0 | xargs -0 mplayer

Cela fonctionne quel que soit le contenu du nom (les deux seuls caractères qui ne peuvent pas apparaître dans un nom de fichier sont la barre oblique et NUL, et la barre oblique ne pose aucun problème dans un chemin de fichier, donc l'utilisation de NUL comme délimiteur de nom couvre tout). Cependant, si vous avez besoin de filtrer les 6 premières entrées, vous avez besoin d'un programme qui gère les 'lignes' terminées par NUL au lieu de newline... et je ne suis pas sûr qu'il en existe.

La première est de loin la plus simple pour le cas spécifique qui nous occupe ; cependant, elle peut ne pas être généralisée pour couvrir les autres scénarios que vous n'avez pas encore énumérés.

1voto

Dick.Guertin Points 19

Étant donné le titre spécifique de ce post, voici ma suggestion :

ls | grep ' ' | tr ' ' '<' | sed 's|<|\\ |g'

L'idée est de convertir les blancs en un caractère unique, comme '<', puis de le transformer en '\', une barre oblique inversée suivie d'un blanc. Vous pouvez ensuite l'intégrer à n'importe quelle commande, comme par exemple :

ls | grep ' ' | tr ' ' '<' | sed 's|<|\\ |g' | xargs -L1 GetFileInfo

La clé réside dans les commandes 'tr' et 'sed' ; vous pouvez utiliser n'importe quel caractère autre que '<', comme '?' ou même un caractère de tabulation.

0voto

Matthew Elvey Points 123

Sous macOS (depuis Monterey/12 et je ne sais pas jusqu'à 10.15/Catalina), si vous avez des espaces dans les noms de fichiers ou les sous-répertoires, vous pouvez utiliser ce qui suit :

mdfind  -0 -onlyin . -name .txt | xargs -0 grep stackoverflow |  wc -l

Comme le note la réponse de Jen :

L'utilitaire xargs lit les chaînes délimitées par des espaces, des tabulations, des nouvelles lignes et des fins de fichiers à partir de l'entrée standard et exécute l'utilitaire avec les chaînes comme arguments.

Il faut éviter d'utiliser l'espace comme délimiteur. Ceci peut être fait en changeant le délimiteur pour xargs. Selon le manuel :

 -0      Change xargs to expect NUL (``\0'') characters as separators,
         instead of spaces and newlines.  This is expected to be used in
         concert with the -print0 function in find(1).

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