web-dev-qa-db-fra.com

Unix: Comment supprimer les fichiers listés dans un fichier

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.

68
Alexander

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
89
nos

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.

47
aks

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.

13
Mark Drago

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.

12
hek2mgl

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.

11
tgdavies

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
11
Ray

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.

4
Uzayr

Dans ce cas particulier, en raison des dangers cités dans d’autres réponses, j’aimerais

  1. Modifier dans, par exemple Vim et :%s/\s/\\\0/g, en échappant tous les espaces avec une barre oblique inverse.

  2. 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.

  3. Exécutez toutes les commandes: $ source 1.txt

2
Evgeni Sergeev

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
1
nthparameter

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 )
0
Quentin

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
0
Chand Priyankara

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
0
Ferroao