Une autre réponse est de forcer xargs
pour traiter les commandes par lots. Par exemple à delete
les fichiers 100
à la fois, cd
dans le répertoire et lancez ceci :
echo *.pdf | xargs -n 100 rm
tl;dr
C'est une limitation du noyau sur la taille de l'argument de la ligne de commande. Utilisez un for
boucle à la place.
Origine du problème
Il s'agit d'un problème système lié à execve
et ARG_MAX
constant. Il y a beaucoup de documentation à ce sujet (voir man execve, le wiki de Debian, les détails d'ARG_MAX).
Fondamentalement, l'expansion produit une commande (avec ses paramètres) qui dépasse le ARG_MAX
limit.Sur le noyau 2.6.23
, la limite a été fixée à 128 kB
. Cette constante a été augmentée et vous pouvez obtenir sa valeur en exécutant :
getconf ARG_MAX
# 2097152 # on 3.5.0-40-generic
Solution :Utiliser for
Boucle
Utilisez un for
boucle comme il est recommandé sur BashFAQ/095 et il n'y a pas de limite sauf pour l'espace RAM/mémoire :
Un essai à blanc pour s'assurer qu'il supprimera ce que vous attendez :
for f in *.pdf; do echo rm "$f"; done
Et exécutez-le :
for f in *.pdf; do rm "$f"; done
Il s'agit également d'une approche portable car glob a un comportement fort et cohérent entre les shells (partie de la spécification POSIX).
Remarque : Comme l'ont noté plusieurs commentaires, c'est en effet plus lent mais plus maintenable car il peut s'adapter à des scénarios plus complexes, par exemple où l'on veut faire plus d'une action.
Solution :Utiliser find
Si vous insistez, vous pouvez utiliser find
mais vraiment n'utilisez pas xargs car il "est dangereux (cassé, exploitable, etc.) lors de la lecture d'une entrée non délimitée par NUL" :
find . -maxdepth 1 -name '*.pdf' -delete
Utilisation de -maxdepth 1 ... -delete
au lieu de -exec rm {} +
autorise find
pour exécuter simplement les appels système requis lui-même sans utiliser de processus externe, donc plus rapidement (grâce au commentaire @chepner).
Références
- Je reçois "Liste d'arguments trop longue". Comment puis-je traiter une grande liste en morceaux? @ laine bord
- execve(2) - page de manuel Linux (recherche pour ARG_MAX);
- Erreur :liste d'arguments trop longue @ wiki Debian ;
- Pourquoi ai-je le message "/bin/sh :liste d'arguments trop longue" lors de la transmission d'arguments entre guillemets ? @ Superutilisateur
find
a un -delete
action :
find . -maxdepth 1 -name '*.pdf' -delete
La raison en est que bash étend en fait l'astérisque à chaque fichier correspondant, produisant une très longue ligne de commande.
Essayez ceci :
find . -name "*.pdf" -print0 | xargs -0 rm
Avertissement : il s'agit d'une recherche récursive qui trouvera (et supprimera) également des fichiers dans des sous-répertoires. Virer sur -f
à la commande rm uniquement si vous êtes sûr de ne pas vouloir de confirmation.
Vous pouvez faire ce qui suit pour rendre la commande non récursive :
find . -maxdepth 1 -name "*.pdf" -print0 | xargs -0 rm
Une autre option consiste à utiliser le -delete
de find drapeau :
find . -name "*.pdf" -delete