web-dev-qa-db-fra.com

 Utilisation de find - Supprimer tous les fichiers/répertoires (sous Linux) sauf un

Si nous voulons supprimer tous les fichiers et répertoires que nous utilisons, rm -rf *.

Mais que se passe-t-il si je veux que tous les fichiers et répertoires soient supprimés d'un coup, sauf un fichier en particulier?

Y at-il une commande pour cela? rm -rf * donne la facilité de suppression en une fois, mais supprime même mon fichier/répertoire préféré.

Merci d'avance

14
kingsmasher1

find peut être un très bon ami:

$ ls
a/  b/  c/
$ find * -maxdepth 0 -name 'b' -Prune -o -exec rm -rf '{}' ';'
$ ls
b/
$ 

Explication:

  • find * -maxdepth 0: sélectionne tout ce qui est sélectionné par * sans descendre dans les répertoires

  • -name 'b' -Prune: ne vous embêtez pas (-Prune) avec tout ce qui correspond à la condition -name 'b'

  • -o -exec rm -rf '{}' ';': appelez rm -rf pour tout le reste

En passant, un autre moyen, peut-être plus simple, consisterait à déplacer ou à renommer votre répertoire favorite de sorte qu'il ne soit pas gênant:

$ ls
a/  b/  c/
$ mv b .b
$ ls
a/  c/
$ rm -rf *
$ mv .b b
$ ls
b/
30
thkala

Réponse courte

ls | grep -v "z.txt" | xargs rm

Détails :

Le processus de pensée pour la commande ci-dessus est:

  • Lister tous les fichiers (ls)
  • Ignorer un fichier nommé "z.txt" (grep -v "z.txt")
  • Supprimer les fichiers répertoriés autres que z.txt (xargs rm)

Exemple

Créez 5 fichiers comme indiqué ci-dessous:

echo "a.txt b.txt c.txt d.txt z.txt" | xargs touch

Liste tous les fichiers sauf z.txt

ls|grep -v "z.txt"

a.txt
b.txt
c.txt
d.txt

Nous pouvons maintenant supprimer (rm) les fichiers listés en utilisant le fichier xargs utility:

ls|grep -v "z.txt"|xargs rm
9
Thyag

Au moins en zsh

rm -rf ^filename

pourrait être une option, si vous ne voulez conserver qu'un seul fichier.

2
Inkane

Vous pouvez le taper directement dans la ligne de commande ou utiliser cette frappe dans le script

files=`ls -l | grep -v "my_favorite_dir"`; for file in $files; do rm -rvf $file; done

P.S. Je suggère que -i permute pour rm afin d’empêcher la suppression de données importantes.

P.P.S Vous pouvez écrire le petit script basé sur cette solution et le placer dans le /usr/bin (par exemple /usr/bin/rmf). Maintenant, vous pouvez l'utiliser comme une application ordinaire:

rmf my_favorite_dir

Le script ressemble à (juste un croquis):

#!/bin/sh

if [[ -z $1 ]]; then
    files=`ls -l`
else
    files=`ls -l | grep -v $1`
fi;

for file in $files; do
    rm -rvi $file
done;
2
maverik

En bash, vous avez l'opérateur !() glob, qui inverse le motif correspondant. Donc, pour tout supprimer sauf le fichier my_file_name.txt, essayez ceci:

shopt -s extglob
rm -f !(my_file_name.txt)

Voir cet article pour plus de détails: http://karper.wordpress.com/2010/11/17/deleting-all-files-in-a-directory-with-exceptions/

1
chiborg

S'il ne s'agit que d'un fichier, un moyen simple consiste à le déplacer vers /tmp ou quelque chose du genre, rm -Rf le répertoire, puis à le déplacer à nouveau. Vous pouvez appeler cela comme une simple commande.

L'autre option consiste à faire un find, puis un grep, ce que vous ne voulez pas (en utilisant -v ou directement en utilisant l'un des prédicats finds), puis rm, des fichiers restants.

Pour un seul fichier, je ferais le premier. Pour n'importe quoi de plus, j'écrirais quelque chose de coutume semblable à ce que disait thkala.

1
Noufal Ibrahim
mv subdir/preciousfile  ./
rm -rf subdir
mkdir subdir
mv preciousfile subdir/

Cela semble fastidieux, mais c'est plutôt sûr

  • évite la logique complexe
  • ne jamais utiliser rm -rf *, ses résultats dépendent de votre répertoire actuel (qui pourrait être / ;-)
  • n'utilisez jamais un * globbing: son développement est limité par ARGV_MAX.
  • vous permet de vérifier l'erreur après chaque commande, et peut-être d'éviter le désastre causé par la commande suivante.
  • évite les problèmes désagréables causés par l'espace ou NL dans les noms de fichiers.
0
wildplasser
cd ..
ln trash/useful.file ./
rm -rf trash/*
mv useful.file trash/
0
Ivan

Je ne connais pas un tel programme, mais je le voulais depuis longtemps. La syntaxe de base serait:

IFS='
' for f in $(except "*.c" "*.h" -- *); do
  printf '%s\n' "$f"
done

Le programme auquel je pense a trois modes:

  • correspondance exacte (avec l'option -e)
  • Correspondance glob (par défaut, comme dans l'exemple ci-dessus)
  • correspondance regex (avec l'option -r)

Il faut exclure les modèles de la ligne de commande, suivis du séparateur --, suivis des noms de fichiers. Les noms de fichiers peuvent également être lus à partir de stdin (si l'option -s est donnée), chacun sur une ligne.

Un tel programme ne devrait pas être difficile à écrire, ni en C ni dans le langage de commande Shell. Et cela fait un bon exercice pour apprendre les bases de Unix. Lorsque vous le faites en tant que programme Shell, vous devez bien sûr surveiller les noms de fichiers contenant des espaces et d'autres caractères spéciaux.

0
Roland Illig

Je vois beaucoup de moyens longs ici, ça marche, mais avec a/b/c/d/e /

 rm -rf *.* !(b*) 

cela supprime tout sauf le répertoire b/et son contenu (en supposant que votre fichier est dans b /. Ensuite, cd b/et

rm -rf *.* !(filename) 

pour supprimer tout le reste, à l'exception du fichier (nommé "nom de fichier") que vous souhaitez conserver.

0
tonybaldwin