J'ai un long fichier texte avec une liste de masques que je veux supprimer
Exemple:
/tmp/aaa.jpg
/var/www1/*
/var/www/qwerty.php
J'ai besoin de les supprimer. Essayé rm `cat 1.txt` et il dit que la liste est trop longue.
Vous avez trouvé cette commande, mais lorsque je vérifie les dossiers de la liste, certains d'entre eux ont encore des fichiers xargs rm <1.txt
L'appel rm manuel supprime les fichiers de ces dossiers.
Ceci n’est pas très efficace, mais fonctionnera si vous avez besoin de modèles globaux (comme dans/var/www/*)
for f in $(cat 1.txt) ; do
rm "$f"
done
Si vous n'avez aucun modèle et que vous êtes certain que vos chemins d'accès dans le fichier ne contiennent pas d'espaces ni d'autres éléments étranges, vous pouvez utiliser xargs comme suit:
xargs rm < 1.txt
En supposant que la liste de fichiers se trouve dans le fichier 1.txt
, faites alors:
xargs rm -r <1.txt
L'option -r
provoque la récursivité dans les répertoires nommés dans 1.txt
.
Si des fichiers sont en lecture seule, utilisez l'option -f
pour forcer la suppression:
xargs rm -rf <1.txt
Soyez prudent avec l'entrée dans tout outil qui effectue des suppressions par programme. Assurez certain que les fichiers nommés dans le fichier d’entrée doivent vraiment être supprimés. Faites particulièrement attention aux fautes de frappe apparemment simples. Par exemple, si vous entrez un espace entre un fichier et son suffixe, il semblera qu'il s'agisse de deux noms de fichier distincts:
file .txt
est en fait deux fichiers distincts: file
et .txt
.
Cela peut sembler moins dangereux, mais si la typo ressemble à ceci:
myoldfiles *
Ensuite, au lieu de supprimer tous les fichiers commençant par myoldfiles
, vous supprimez myoldfiles
et all non-dot-files et les répertoires du répertoire actuel. Probablement pas ce que tu voulais.
xargs -I{} sh -c 'rm {}' < 1.txt
devrait faire ce que vous voulez. Soyez prudent avec cette commande, car une entrée incorrecte dans ce fichier pourrait causer beaucoup de problèmes.
Cette réponse a été modifiée après que @tdavies ait signalé que l'original ne développait pas Shell.
Utilisez ceci:
while IFS= read -r file ; do rm -- "$file" ; done < delete.list
Si vous avez besoin d'une extension globale, vous pouvez omettre de citer $file
:
IFS=""
while read -r file ; do rm -- $file ; done < delete.list
Mais sachez que les noms de fichiers peuvent contenir du contenu "problématique" et que j'utiliserais la version non citée. Imaginez ce motif dans le fichier
*
*/*
*/*/*
Cela effacerait beaucoup du répertoire courant! Je vous encourage à préparer la liste de suppression de manière à ce que les motifs globaux ne soient plus nécessaires, puis utilisez la citation comme dans mon premier exemple.
Vous pouvez utiliser ce one-liner:
cat 1.txt | xargs echo rm | sh
Qui fait l'expansion de Shell mais exécute rm
le nombre minimum de fois.
Vous pouvez utiliser '\ n' pour définir le caractère de nouvelle ligne comme séparateur.
xargs -d '\n' rm < 1.txt
Faites attention avec -rf car il peut supprimer ce que vous ne voulez pas si le 1.txt contient des chemins avec des espaces. C'est pourquoi le nouveau délimiteur de ligne est un peu plus sûr.
Sur les systèmes BSD, vous pouvez utiliser l'option -0 pour utiliser les nouveaux caractères de ligne comme délimiteurs, comme ceci:
xargs -0 rm < 1.txt
cat 1.txt | xargs rm -f | bash
Exécutez la commande effectuera ce qui suit pour les fichiers uniquement.
cat 1.txt | xargs rm -rf | bash
Exécutez la commande aura le comportement récursif suivant.
Dans ce cas particulier, en raison des dangers cités dans d’autres réponses, j’aimerais
Modifier dans, par exemple Vim et :%s/\s/\\\0/g
, en échappant tous les espaces avec une barre oblique inverse.
Puis :%s/^/rm -rf /
, en ajoutant la commande. Avec -r
, vous n'avez pas à vous soucier de la liste des répertoires après les fichiers qui y sont contenus. Avec -f
, vous ne vous plaindrez pas des fichiers manquants ou des doublons.
Exécutez toutes les commandes: $ source 1.txt
Voici un autre exemple en boucle. Celui-ci contient également une 'instruction-if' à titre d'exemple pour vérifier si l'entrée est un 'fichier' (ou un 'répertoire' par exemple):
for f in $(cat 1.txt); do if [ -f $f ]; then rm $f; fi; done
Juste pour fournir un autre moyen, vous pouvez aussi simplement utiliser la commande suivante
$ cat to_remove
/tmp/file1
/tmp/file2
/tmp/file3
$ rm $( cat to_remove )
Ici, vous pouvez utiliser un ensemble de dossiers de deletelist.txt while en évitant certains motifs aussi
foreach f (cat deletelist.txt)
rm -rf ls | egrep -v "needthisfile|*.cpp|*.h"
end
Cela permettra aux noms de fichiers d'avoir des espaces (exemple reproductible).
# Select files of interest, here, only text files for ex.
find -type f -exec file {} \; > findresult.txt
grep ": ASCII text$" findresult.txt > textfiles.txt
# leave only the path to the file removing suffix and prefix
sed -i -e 's/:.*$//' textfiles.txt
sed -i -e 's/\.\///' textfiles.txt
#write a script that deletes the files in textfiles.txt
IFS_backup=$IFS
IFS=$(echo "\n\b")
for f in $(cat textfiles.txt);
do
rm "$f";
done
IFS=$IFS_backup
# save script as "some.sh" and run: sh some.sh