web-dev-qa-db-fra.com

Supprimer sauf certains fichiers / répertoires dans un script; besoin de révision

J'ai le même problème que cette question Comment supprimer tous les fichiers/dossiers du dossier sauf quelques dossiers? plusieurs fois. C'est la raison pour laquelle j'ai voulu écrire moi-même un script pour une commande rmnot. Cela devrait prendre un nombre arbitraire de fichiers, même avec des caractères génériques si nécessaire, et supprimer tout (pas recursevely) dans le même répertoire à l'exception de ces fichiers. Exemple typique serait:

rmnot *tex *bib *png

Mon script fonctionne, mais étant donné que je suis inexpérimenté et que je veux l'apprendre correctement, existe-t-il un moyen plus élégant d'écrire ce script?

#!/bin/zsh

insert="-name . -or -name .."

for i in {1..$#}; do
    insert="$insert -or -name ${(P)i}"
done

insert="\( $insert \)"

eval "find -not $insert -exec rm {} \;"

PS: Je dois utiliser ZSH à cause de la double substitution ${(P)i} toute autre solution fonctionnerait également en bash, je pense.

====== Version optimisée =====

 #!/bin/bash

 insert="-name . -or -name .."

 for i; do
    insert="$insert -or -name $i"
 done

 insert="\( $insert \)"

 find -maxdepth 1 -not $insert -delete
2
mcocdawc

Vous n'avez même pas besoin d'un script. Si vous utilisez bash, vous pouvez activer extglob et donner des motifs négatifs:

$ ls
foo.avi  foo.bbl  foo.bib  foo.log  foo.png  foo.tex  foo.txt  foo.wav
$ shopt -s extglob
$ rm !(*tex|*bib|*png)
$ ls
foo.bib  foo.png  foo.tex

Comme expliqué dans man bash:

   If the extglob Shell option is enabled using the shopt builtin, several
   extended  pattern  matching operators are recognized.  In the following
   description, a pattern-list is a list of one or more patterns separated
   by a |.  Composite patterns may be formed using one or more of the fol‐
   lowing sub-patterns:

          ?(pattern-list)
                 Matches zero or one occurrence of the given patterns
          *(pattern-list)
                 Matches zero or more occurrences of the given patterns
          +(pattern-list)
                 Matches one or more occurrences of the given patterns
          @(pattern-list)
                 Matches one of the given patterns
          !(pattern-list)
                 Matches anything except one of the given patterns

Avec zsh, l'équivalent est:

setopt extended_glob
rm ^(*tex|*bib|*png)

Si vous voulez toujours écrire un script pour cela, concaténez simplement les arguments que vous lui donnez, mais n'utilisez pas de caractères génériques (*), laissez le script les ajouter (merci à @Helios d'avoir suggéré une version plus simple):

#!/usr/bin/env bash

## Iterate over the arguments
for i
do
    ## Add them to the pattern to be excluded
    pat+="*$i|"
done
## Activate extglob
shopt -s extglob
## Delete non-matching files
rm !(${pat})
10
terdon