Pourquoi xargs ne peut-il pas supprimer les répertoires avec des espaces dans leurs noms, et comment résoudre ce problème?
76 find . -type d |xargs rm -rf
77 rm -rf fire\ hydrant/
78 rm -rf wine\ glass/
79 rm -rf tennis\ racket/
80 rm -rf traffic\ light/
81 rm -rf parking\ meter/
82 rm -rf teddy\ bear/
83 rm -rf sports\ ball/
84 rm -rf cell\ phone/
85 rm -rf stop\ sign/
86 rm -rf dining\ table/
87 rm -rf potted\ plant/
Corrigez-le en utilisant -print0
dans find
et xargs -0
dans xargs
pour que les deux commandes utilisent le caractère NULL comme séparateur à la place de l'espace:
find . -type d -print0 | xargs -0 rm -rf
Voici une bonne explication de la raison pour laquelle elle tombe en panne et du fonctionnement de ce correctif depuis La ligne de commande Linux de William E. Shotts Jr .
Traitement des noms de fichiers drôles
Les systèmes de type Unix permettent des espaces intégrés (et même des nouvelles lignes!) Dans les noms de fichiers. Cela pose des problèmes pour des programmes comme
xargs
qui construisent des listes d'arguments pour d'autres programmes. Un espace incorporé sera traité comme un délimiteur et la commande résultante interprétera chaque mot séparé par un espace comme un argument séparé. Pour résoudre ce problème, find et xarg permettent l'utilisation facultative d'un caractère null en tant que séparateur d'arguments. Un caractère nul est défini dans ASCII en tant que caractère représenté par le chiffre zéro (par exemple, le caractère espace défini dans ASCII en tant que caractère représenté par le caractère numéro 32). La commande find fournit l'action -print0, qui produit une sortie séparée par un null, et la commande xargs a l'option --null, qui accepte une entrée séparée par un null. Voici un exemple:find ~ -iname '*.jpg' -print0 | xargs --null ls -l
En utilisant cette technique, nous pouvons nous assurer que tous les fichiers, même ceux contenant des espaces incorporés dans leurs noms, sont gérés correctement.
(-0
est la version abrégée de l'option --null
.)
Vous n'avez pas besoin de xargs
, find
elle-même peut le faire de manière robuste avec la gestion:
tout type de noms de fichiers possibles
sans déclencher ARG_MAX
Si les répertoires sont vides, utilisez l'action -delete
:
find . -type d -delete
S'il n'est pas vide, utilisez rm -r
dans l'action -exec
:
find . -type d -exec rm -r {} +
Si vous insistez pour utiliser xargs
, vous pouvez utiliser newline comme séparateur d'arguments entrants pour tous les noms de répertoire sans nouvelle ligne.
find . -type d | xargs -d $'\n' rm -r
Le meilleur moyen est de séparer les fichiers NUL et d’en traiter avec l’option -0
de xargs
:
find . -type d -name 'foo bar*' -print0 | xargs -0 rm -r
Pour tous les rm -r
utilisés, ajoutez -f
c'est-à-dire do rm -rf
si nécessaire.
Pour supprimer spécifiquement tous les sous-répertoires comportant des espaces, la commande la plus simple serait:
find . -type d -name "* *" -exec rm -rf {} +
C'est la même approche que celle proposée par heemayl, la seule différence étant le filtrage -name
.