web-dev-qa-db-fra.com

Supprimer tous les fichiers sauf les fichiers avec l'extension pdf dans un répertoire

J'ai un répertoire qui contient les éléments suivants:

x.pdf
y.Zip
z.mp3
a.pdf

Je souhaite supprimer tous les fichiers sauf x.pdf et a.pdf. Comment est-ce que je fais ceci du terminal? Il n'y a pas de sous-répertoires, aucune récursivité n'est donc nécessaire.

50
Starkers
cd <the directory you want>
find . -type f ! -iname "*.pdf" -delete
  • La première commande vous mènera au répertoire dans lequel vous voulez supprimer vos fichiers
  • La deuxième commande supprimera tous les fichiers sauf ceux se terminant par .pdf dans le nom du fichier.

Par exemple, s'il existe un répertoire appelé temp dans votre dossier personnel:

cd ~/temp

puis supprimez les fichiers:

find . -type f ! -iname "*.pdf" -delete

Cela supprimera tous les fichiers sauf xyz.pdf.

Vous pouvez combiner ces deux commandes pour:

find ~/temp -type f ! -iname "*.pdf" -delete

. est le répertoire en cours. ! signifie prendre tous les fichiers sauf ceux avec .pdf à la fin. -type f sélectionne uniquement les fichiers, pas les répertoires. -delete signifie le supprimer.

REMARQUE: cette commande supprimera tous les fichiers (sauf les fichiers pdf mais les fichiers cachés) du répertoire actuel ainsi que de tous les sous-répertoires. ! doit précéder -name. simplement -name inclura seulement .pdf, alors que -iname inclura les deux .pdf et .PDF

Pour supprimer uniquement dans le répertoire en cours et non dans les sous-répertoires, ajoutez -maxdepth 1:

find . -maxdepth 1 -type f ! -iname "*.pdf" -delete
63
Edward Torvalds

Avec le shell étendu de bash, vous pouvez supprimer tous les fichiers avec des extensions autres que .pdf en utilisant

rm -- *.!(pdf)

Comme indiqué par @pts, les caractères -- indiquent la fin de toutes les options de commande; sécurisez la commande dans le cas très rare de fichiers dont le nom commence par un caractère -.

Si vous souhaitez supprimer des fichiers sans extension ainsi que ceux avec des extensions autres que .pdf, alors, comme l'a souligné @DennisWilliamson, vous pouvez utiliser

rm -- !(*.pdf)

La navigation étendue doit être activée par défaut, mais sinon, vous pouvez le faire en utilisant

shopt -s extglob

Surtout si vous souhaitez utiliser ceci dans un script, il est important de noter que si l'expression ne correspond à rien (c'est-à-dire s'il n'y a pas de fichiers non-pdf dans le répertoire), alors par défaut, le glob sera passé non développé au rm, ce qui entraîne une erreur telle que

rm: cannot remove `*.!(pdf)': No such file or directory

Vous pouvez modifier ce comportement par défaut à l'aide de l'option Shell nullglob, qui a toutefois son propre problème. Pour une discussion plus approfondie, voir NullGlob - Wiki de Greg

42
steeldriver

Supprimer de la corbeille :

$ cd <the directory you want>
$ gvfs-trash !(*.pdf)

Ou via la commande mv (mais de cette manière, vous ne pourrez pas la restaurer depuis la corbeille, car elle n'enregistre pas les informations .trashinfo. Cela signifie donc que vous avez déplacé vos fichiers vers une destination où il est comme suit).

mv !(*.pdf) ~/.local/share/Trash/files
18
αғsнιη

La méthode la plus simple: créez un autre répertoire quelque part (si vous ne supprimez que dans un répertoire, pas de manière récursive, il peut même s'agir d'un sous-répertoire); déplacez tous les fichiers .pdf là-bas; supprimer tout le reste; déplacez le pdf en arrière; supprimer le répertoire intermédiaire.

Rapide, facile, vous pouvez voir exactement ce que vous faites. Assurez-vous simplement que le répertoire intermédiaire se trouve sur le même périphérique que le répertoire que vous êtes en train de nettoyer afin que les déplacements soient renommés et non des copies!

14
Jerry

Utilisez GLOBIGNORE de bash:

GLOBIGNORE=x.pdf:a.pdf
rm *
unset GLOBIGNORE

De la page de manuel de bash:

 GLOBIGNORE: 
 
 Une liste de motifs séparés par deux points définissant l’ensemble 
 De noms de fichiers à ignorer lors du développement du chemin. 

Un test rapide:

mkdir /tmp/foooooo
cd /tmp/foooooo
touch x.pdf y.Zip z.mp3 a.pdf
GLOBIGNORE=x.pdf:a.pdf
ls -1 *

Sortie:

 y.Zip 
 z.mp3 
4
Cyrus

Soyez prudent et composez: utilisez xargs

Voici une approche que j’aime bien, car cela me permet d’être très prudent: composez un moyen d’afficher uniquement les fichiers que je veux supprimer, puis envoyez-les à rmen utilisant xargsname__. Par exemple:

  • lsme montre tout
  • ls | grep pdf me montre les fichiers que je veux conserver. Hmm.
  • ls | grep -v pdf montre le contraire: tout sauf ce que je veux garder. En d'autres termes, il affiche la liste des choses que je veux supprimer. Je peux le confirmer avant de faire quoi que ce soit de dangereux.
  • ls | grep -v pdf | xargs rm envoie exactement cette liste à rmpour suppression

Comme je l'ai dit, j'aime principalement ceci pour la sécurité qu'il procure: pas de rm * accidentel pour moi. Deux autres avantages:

  • C'est composable; vous pouvez utiliser lsou findpour obtenir la liste initiale, comme vous préférez. Vous pouvez utiliser ce que vous voulez pour restreindre cette liste: un autre grepname__, un awkou autre chose. Si vous ne devez supprimer que les fichiers dont le nom contient une couleur, vous pouvez le construire de la même manière.
  • Vous pouvez utiliser chaque outil pour son objectif principal. Je préfère utiliser findpour trouver et rmà supprimer, au lieu de devoir garder à l'esprit que findaccepte un indicateur -delete. Et si vous faites cela, encore une fois, vous pouvez composer des solutions alternatives. peut-être qu'au lieu de rmname__, vous pourriez créer une commande trashqui déplace le fichier dans la corbeille (en autorisant "undeletion") et le rediriger vers elle au lieu de rmname__. Vous n'avez pas besoin que findprenne en charge cette option, vous devez simplement la suivre.

Mettre à jour

Voir les commentaires de @pabouk pour savoir comment modifier cela afin de traiter certains cas Edge, tels que les sauts de ligne dans les noms de fichiers, les noms de fichiers tels que my_pdfs.Zip, etc.

3
Nathan Long

Je résous généralement ces problèmes à partir de l'interpréteur interactif Python:

mic@mic ~ $ python
>>> import os
>>> for f in os.listdir('.'):
...   if not f.endswith('.pdf'):
...     os.remove(f)

Il peut être plus long qu'un one-liner avec find ou xargs, mais il est extrêmement résistant, et je sais exactement ce que cela fait, sans avoir à le rechercher au préalable.

3
mic_e

meilleure réponse (par rapport à ma réponse précédente) à cette question sera en utilisant la puissante commande filename__.

$ file -i abc.pdf
abc: application/pdf; charset=binary

maintenant votre problème:

cd <the directory you want to search in>
for var in ./*
do
if file -i "$var" | grep -q 'application/pdf\;'
then
echo "$var"
fi
done

le travail de la commande fordonne les fichiers du répertoire en cours sous la forme de la variable $var. if-then commande les noms des fichiers pdf en prenant le statut de sortie de 0 à partir de la commande file -i "$var" | grep -q 'application/pdf\;', elle donnera le statut de sortie de 0 uniquement si elle trouve des fichiers pdf.

2
Edward Torvalds

manière Shell

$ ksh -c 'for i in ./*; do case $i in *.pdf)continue;; *)rm "$i";; esac;done'

Pratiquement POSIX et compatible avec n’importe quel shell Bourne-style (ksh, bash, dash). Convient parfaitement aux scripts portables et lorsque vous ne pouvez pas utiliser le globbing étendu de bash.

Perl:

$ Perl -le 'opendir(my $d,"."); foreach my $f (grep(-f && !/.pdf/ , readdir($d))){unlink $f};closedir $d'                                                             

Ou légèrement plus propre:

$ Perl -le 'opendir(my $d,"."); map{ unlink $_ } grep(-f "./$_" && !/.pdf/ , readdir($d));closedir $d'

python alternatif

python -c 'import os;map(lambda x: os.remove(x), filter(lambda x: not x.endswith(".pdf"),os.listdir(".")))'
1
rm $(ls -lo|grep -v [Pp][Dd][Ff]$|awk '{print $7}')

Attention! Mieux vaut essayer d'abord

ls -l $(ls -lo|grep -v [Pp][Dd][Ff]$|awk '{print $7}')
rm -i -- !(*@(a|x).pdf)

Lire en tant que, supprimez tous les fichiers qui ne sont pas a.pdf ou x.pdf.

Cela fonctionne en utilisant 2 globs étendus, la !() extérieure pour nier le glob contenu, qui lui-même exige que le glob corresponde à un ou plusieurs des modèles a ou x avant le suffixe .pdf. Voir glob # extglob .

$ ls -a
.dotfile1 .dotfile2 a.pdf x.pdf y.Zip z.mp3

$ echo -- !(a.pdf)
-- x.pdf y.Zip z.mp3

$ echo -- !(x.pdf)
-- a.pdf y.Zip z.mp3

$ echo -- !(a.pdf|x.pdf)
-- y.Zip z.mp3

$ echo -- !(@(a|x).pdf)   # NOTE.that this matches the .dotfiles* as well
-- . .. .dotfile1 .dotfile2 y.Zip z.mp3

$ echo -- !(*@(a|x).pdf)  # but this doesn't
-- y.Zip z.mp3

$ echo rm -i -- !(*@(a|x).pdf)
rm -i -- y.Zip z.mp3
1
shalomb

Faites attention à ce que vous supprimez!

Un moyen sûr de le tester avant d’essayer de supprimer consiste à tester d’abord avec ls, car certains comportements non détectés pourraient supprimer des fichiers indésirables. Et vous pouvez le faire directement en dehors du répertoire. ls est similaire à rm, donc:

ls sub/path/to/files/!(*.pdf)

Cela va lister

y.Zip
z.mp3

Et maintenant, vous pouvez voir ce que vous supprimez et pouvez les supprimer en toute sécurité:

rm sub/path/to/files/!(*.pdf)

Et c'est tout. Vous pouvez utiliser le caractère générique * pour être plus sélectif, par exemple en ne conservant que les documents de cours de programmation:

rm sub/path/to/files/!(*programming*)
0
KeitelDOG