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


Réponses:


11

Si vous ne pouvez pas supprimer le répertoire, vous pouvez toujours utiliser find.

find . -maxdepth 1 -type f -exec rm -f {} \;

Cela supprimera tous les fichiers du répertoire actuel, et uniquement le répertoire actuel (pas les sous-répertoires).


presque parfait (voir mon article aussi)
asdmin

2
Sur Linux, vous pouvez le faire encore plus rapidement en utilisant "+" au lieu de "\;". Cela entraînera la suppression de plus de fichiers par "rm" en une seule fois.
Thomas

5
Encore plus rapide: find dir/to/delete -delete(ne génère pas de rmprocessus par fichier à supprimer).
Morten Siebuhr

Morten: Il n'a jamais mentionné vouloir supprimer le répertoire lui-même, a déclaré onky les fichiers. find dir/to/delete -type f -delete
richo

21
trouver . -maxdepth 1 -type f -exec rm -f {} \;

cela prend simplement trop de temps (un exec de rm par fichier).

celui-ci est beaucoup plus efficace:

trouver . -maxdepth 1 -type f -print0 | xargs -r0 rm -f

car il faut autant de noms de fichiers que d'arguments pour rm autant que possible, puis exécute rm avec la prochaine charge de noms de fichiers ... il peut arriver que rm ne soit appelé que 2 ou 3 fois.


5
Heureux de voir quelqu'un savoir comment fonctionne find ... Envisagez également avec l'action -delete de la nouvelle commande gnu find ou la commande -exec {} + qui agit comme xargs. Voir la section Actions de 'man find'.
Kyle Brandt le

Je ne connaissais pas -exec cmd {} +. Cela semble plutôt utile. Un peu plus générique que -delete :)
David Pashley

-delete peut être bien, mais je préfère personnellement les commandes qui peuvent être utilisées sur une variété de machines. Les systèmes Solaris avec lesquels je travaille sont plus anciens, donc -delete ne fonctionnerait pas sur eux
asdmin

2
Ajouter ionicejuste avant rmest une bonne idée si l'ordinateur est utilisé par d'autres personnes en même temps.
Hubert Kario

6

Ces deux solutions permettront de contourner le problème. Il y a une analyse des performances respectives de chaque technique ici .

find . -name WHATEVER -exec rm -rf {} \;

ou

ls WHATEVER | xargs rm -rf

Le problème provient de l'expansion de bash "*" avec chaque élément unique dans le répertoire. Ces deux solutions fonctionnent à la place dans chaque fichier.


2
La solution de recherche est plus lente avec de nombreux fichiers car elle appelle la commande rm pour chaque fichier. La solution xargs est plus rapide mais elle ne fonctionne que lorsque les noms de fichiers ne contiennent pas d'espaces (sinon vous avez besoin de GNU find et find . -print0 | xargs -0 rm).
robcast

"find. -name WHATEVER -print0 | xargs -0 rm -rf" sera plus efficace. find fourchera un rm pour chaque fichier, alors que xargs le réduira au minimum. Vous avez besoin de -print0 et -0 pour gérer les fichiers avec des espaces. Vous voulez probablement aussi utiliser -depth sur find, donc il fait une première recherche approfondie.
David Pashley

La commande ls ne fonctionnera pas, car cela renvoie également "la liste des arguments est trop longue"
Brent

2
Vous faites " ls *", et le " *" se développe dans la liste d'arguments que votre shell se plaint d'être trop long. Faites " ls ." à la place (ou montez d'un niveau de répertoire et faites " ls [dirname]").
James Sneeringer

la deuxième ligne de commande (ls WHATEVER | xargs rm -rf) ne fonctionnerait pas pour la même raison que la question ne fonctionnait pas: WHATEVER serait substitué par shell à une longueur dépassant
asdmin

3

J'ai pu le faire en sauvegardant un niveau:

cd ..

Et en cours d'exécution:

rm directory name -rf

Et puis recréer le répertoire.


1
cela ne fonctionne que si vous n'avez pas besoin d'avoir le répertoire en permanence et tous les fichiers et répertoires doivent être supprimés récursivement. la plupart des cas dans ma vie, cette façon n'aurait pas fonctionné.
asdmin

2

Toutes ces invocations de recherche sont très agréables mais je me souviens rarement exactement de la nomenclature nécessaire lorsque je suis pressé: j'utilise plutôt ls. Comme quelqu'un le mentionne, ls. fonctionnerait mais je préfère ls -1 comme dans:

ls -1 | xargs -n 100 rm -rf

Le chiffre -n xxx est assez sûr pour jouer car le dépassement du maximum sera soit auto-corrigé (si la taille-max est dépassée; voir -s) ou si l'args-max pour une application est dépassé, il sera généralement plutôt évident.

Il convient de noter que grep est pratique à insérer au milieu de cette chaîne lorsque vous souhaitez uniquement supprimer un sous-ensemble de fichiers dans un grand répertoire et que vous ne souhaitez pas utiliser find pour une raison quelconque.

Cette réponse suppose que vous utilisez les utilitaires de base Gnu pour vos ls, xargs, etc.


Est-ce que cela fonctionnera avec un répertoire trop grand pour que "ls" fonctionne? (même erreur - liste d'arguments trop longue)
Brent

Oui Brent: assurez-vous simplement de ne pas utiliser de spécification de fichier lorsque vous invoquez ls. Utilisez uniquement le -1 (tiret un) comme indiqué ci-dessus. Et comme expliqué ci-dessus, utilisez grep après le ls si vous devez coupler la liste des fichiers. Si vous obtenez l'erreur "trop ​​longue" après vous être assuré que vous n'utilisez pas de caractères génériques avec ls, alors peut-être que xargs se plaint. Utilisez 'xargs -n 5' au lieu de 'xargs -n 100' et vous devriez certainement être en sécurité, même si c'est un peu plus lent.
rixtertech

1

Vous pouvez utiliser l' -exec +option pour trouver celui qui tentera d'exécuter rm le moins de fois possible, ce qui pourrait être plus rapide.

find . -type f -exec rm '{}' +

0

Voici une version pour supprimer un grand nombre de fichiers lorsque le système doit rester réactif.

Il fonctionne en émettant le travail en petits lots (100 fichiers par défaut) et en attendant un peu que les autres travaux se terminent.

A parfaitement fonctionné pour supprimer plus d'un demi-million de fichiers d'un seul répertoire sur ext3. Il imprime le pourcentage effectué comme un petit bonus

noOfFiles=`ls -U | wc -l`
n=0
while (ls -U | tail -n 100 | xargs rm -f); do 
   n=$((n+100));
   sync;
   echo -en "$((n*100/noOfFiles))%, ($n of $noOfFiles)\r";
   sleep 5;
done

0

Résout les erreurs «argument trop long» ou «impossible d'allouer de la mémoire»

Cela a fait l'affaire sur plus de 220 000 fichiers dans le dossier de session ....

Avantage: commence à supprimer instantanément les fichiers

chemin cd / vers / dossier
ls -f | xargs rm -f -v

CLIQUEZ pour une capture d'écran des fichiers supprimés - (supprimé tous les fichiers en ~ 15min)

-f (après ls) empêche le tri préalable

-v (après rm) affiche chaque fichier comme étant supprimé

-f (après rm) passe sans aucune invite sur les fichiers protégés en écriture

Conseil: Renommez d'abord le dossier (ex session en session_old) pour empêcher l'ajout de fichiers générés automatiquement pendant que vous essayez de supprimer des fichiers. Vous pouvez refaire manuellement le répertoire d'origine s'il ne le fait pas automatiquement comme dans mon cas


Quoi de neuf dans votre réponse qui manquait aux précédentes?
user2233709
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.