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.
cd <the directory you want>
find . -type f ! -iname "*.pdf" -delete
.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.
!
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
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
$ 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
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!
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
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 à rm
en utilisant xargs
name__. Par exemple:
ls
me montre toutls | 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 à rm
pour suppressionComme je l'ai dit, j'aime principalement ceci pour la sécurité qu'il procure: pas de rm *
accidentel pour moi. Deux autres avantages:
ls
ou find
pour obtenir la liste initiale, comme vous préférez. Vous pouvez utiliser ce que vous voulez pour restreindre cette liste: un autre grep
name__, un awk
ou 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.find
pour trouver et rm
à supprimer, au lieu de devoir garder à l'esprit 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
name__, vous pourriez créer une commande trash
qui déplace le fichier dans la corbeille (en autorisant "undeletion") et le rediriger vers elle au lieu de rm
name__. Vous n'avez pas besoin que find
prenne en charge cette option, vous devez simplement la suivre.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.
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.
meilleure réponse (par rapport à ma réponse précédente) à cette question sera en utilisant la puissante commande file
name__.
$ 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
donne 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.
$ 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 -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 -c 'import os;map(lambda x: os.remove(x), filter(lambda x: not x.endswith(".pdf"),os.listdir(".")))'
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
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*)