GNU/Linux >> Tutoriels Linux >  >> Linux

Erreur de liste d'arguments trop longue pour les commandes rm, cp, mv

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

Linux
  1. Aide-mémoire pour les commandes Linux courantes

  2. Ubuntu – Liste d'arguments trop longue ?

  3. Vous ne trouvez pas -lm ?

  4. Bash for loop Exemples

  5. Comment limiter la profondeur de la liste de fichiers récursifs ?

Commandes FreeDOS pour les fans de Linux

La ligne de commande s'écrase lorsque les commandes deviennent trop longues

bash :/bin/tar :liste d'arguments trop longue lors de la compression de nombreux fichiers avec tar

Comment lister les dossiers à l'aide des commandes bash ?

ps :la commande complète est trop longue

Comment puis-je supprimer tous les fichiers d'un répertoire lorsqu'il signale une liste d'arguments trop longue