Supprimer tous les fichiers à l'exception des fichiers avec l'extension pdf dans un répertoire

48

J'ai un répertoire contenant 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 puis-je le faire depuis le terminal? Il n'y a pas de sous-répertoires, donc pas besoin de récursivité.

    
posée Starkers 01.12.2014 - 12:47
la source

11 réponses

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

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

cd ~/temp

puis supprimez les fichiers:

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

Ceci 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 supprime tous les fichiers (sauf les fichiers pdf mais y compris les fichiers cachés) dans le répertoire en cours ainsi que dans tous les sous-répertoires. ! doit venir avant -name . simplement -name inclura seulement .pdf , tandis que -iname inclura à la fois .pdf et .PDF

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

find . -maxdepth 1 -type f ! -iname "*.pdf" -delete
    
réponse donnée edward torvalds 01.12.2014 - 12:51
la source
41

Avec le shell de globalisation é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 des options de commande, ce qui rend la commande sûre dans les rares cas où les noms commencent par un caractère - .

Si vous souhaitez supprimer des fichiers sans extension, ainsi que ceux avec des extensions autres que .pdf , alors comme le fait remarquer @DennisWilliamson, vous pouvez utiliser

rm -- !(*.pdf)

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

shopt -s extglob

Surtout si vous avez l'intention de l'utiliser 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), le glob sera transmis par défaut unexpanded à la commande rm , entraînant une erreur comme

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

Vous pouvez modifier ce comportement par défaut en utilisant l’option nullglob shell, qui a cependant son propre problème. Pour une discussion plus approfondie, voir NullGlob - Wiki de Greg

    
réponse donnée steeldriver 01.12.2014 - 13:11
la source
17

Supprimer la corbeille :

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

Ou via la commande mv (mais vous ne pouvez pas la restaurer depuis Trash car elle n’enregistre pas d’informations .trashinfo, ce qui signifie que vous avez déplacé vos fichiers vers une destination où elle se trouve. comme suit).

mv !(*.pdf) ~/.local/share/Trash/files
    
réponse donnée αғsнιη 01.12.2014 - 17:09
la source
14

L'approche la plus simple: créer 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éplacer tous les fichiers .pdf supprimer tout le reste; déplacer le fichier pdf; 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 nettoyez afin que les déplacements soient renommés et non copiés!

    
réponse donnée Jerry 01.12.2014 - 16:45
la source
4

Utilisez GLOBIGNORE de bash:

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

De la page de manuel de bash:

GLOBIGNORE:

            A colon-separated list of patterns defining the set
            of filenames to be ignored by pathname expansion.

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
    
réponse donnée Cyrus 06.06.2015 - 18:51
la source
3

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

[email protected] ~ $ python
>>> import os
>>> for f in os.listdir('.'):
...   if not f.endswith('.pdf'):
...     os.remove(f)

Il peut être plus long qu’un simple trait avec find ou xargs , mais il est extrêmement résistant, et je sais exactement ce qu’il fait, sans avoir à le rechercher d’abord.

    
réponse donnée mic_e 02.12.2014 - 22:58
la source
2

Soyez prudent et composez: utilisez xargs

Voici une approche que j'aime bien, car elle me permet de faire très attention: composez un moyen de montrer uniquement les fichiers que je veux supprimer, puis envoyez-les à rm en utilisant xargs . Par exemple:

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

Comme je l’ai dit, je l’aime surtout pour la sécurité qu’elle procure: pas de rm * accidentel pour moi. Deux autres avantages:

  • C'est composable; vous pouvez utiliser ls ou find pour obtenir la liste initiale, comme vous préférez. Vous pouvez utiliser tout ce que vous voulez dans le processus de rétrécissement de cette liste - un autre grep , un autre awk ou autre. Si vous ne deviez supprimer que des fichiers dont le nom contient une couleur, vous pourriez le créer de la même manière.
  • Vous pouvez utiliser chaque outil pour son objectif principal. Je préfère utiliser find pour la recherche et rm pour la suppression, au lieu de devoir se rappeler que find accepte un indicateur -delete . Et si vous faites cela, encore une fois, vous pouvez composer des solutions alternatives; peut-être qu'au lieu de rm , vous pourriez créer une commande trash qui déplace le fichier vers la corbeille (permettant "undeletion") et le redirigeant au lieu de rm . Vous n'avez pas besoin que find prenne en charge cette option, vous venez juste d'y accéder.

Mise à jour

Voir les commentaires de @pabouk pour savoir comment modifier ceci pour gérer certains cas extrêmes, tels que les sauts de ligne dans les noms de fichiers, les noms de fichiers tels que my_pdfs.zip , etc.

    
réponse donnée Nathan Long 01.12.2014 - 22:39
la source
2

Une meilleure réponse à cette question (comparée à ma réponse précédente) sera d'utiliser la puissante commande file .

$ 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 for est de donner les fichiers dans le répertoire courant sous la forme de la variable $var . La commande if-then affiche les noms des fichiers pdf en prenant le statut de sortie de la commande 0 from file -i "$var" | grep -q 'application/pdf\;' , elle donnera le statut de sortie de 0 uniquement si elle trouve des fichiers pdf.

    
réponse donnée edward torvalds 04.06.2015 - 18:39
la source
1
rm $(ls -lo|grep -v [Pp][Dd][Ff]$|awk '{print }')

Attention! Mieux vaut essayer en premier

ls -l $(ls -lo|grep -v [Pp][Dd][Ff]$|awk '{print }')
    
réponse donnée Martín-Blas Pérez Pinilla 03.12.2014 - 16:08
la source
1
rm -i -- !(*@(a|x).pdf)

Lisez comme, supprimez tous les fichiers qui ne sont pas a.pdf ou x.pdf .

Cela fonctionne en utilisant 2 globs étendus, le !() externe pour annuler le glob contenu qui lui-même exige que le glob doit correspondre à un ou plusieurs des motifs 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
    
réponse donnée shalomb 17.05.2015 - 12:48
la source
1

façon shell portable

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

A peu près POSIX et compatible avec tout shell Bourne ( ksh , bash , dash ). Convient parfaitement aux scripts portables et lorsque vous ne pouvez pas utiliser le shell global é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(".")))'
    
réponse donnée Sergiy Kolodyazhnyy 08.11.2017 - 10:16
la source

Lire d'autres questions sur les étiquettes