Remove exceto alguns arquivos / diretórios em um script; precisa de revisão

2

Eu tenho o mesmo problema que esta questão Como excluir todos os arquivos / pastas da pasta, exceto algumas pastas? várias vezes. Esta é a razão pela qual eu queria me escrever um script para um comando rmnot. Ele deve ter um número arbitrário de arquivos, mesmo com curingas, se necessário, e excluir qualquer coisa (não recursivamente) no mesmo diretório, exceto para esses arquivos. Exemplo típico seria:

rmnot *tex *bib *png

Meu script funciona, mas como sou inexperiente e quero aprender da maneira correta, existe uma maneira mais elegante de escrever esse 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: Eu tenho que usar ZSH por causa da substituição dupla ${(P)i} qualquer outra coisa funcionaria na bash, eu acho.

====== Versão otimizada =====

 #!/bin/bash

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

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

 insert="\( $insert \)"

 find -maxdepth 1 -not $insert -delete
    
por mcocdawc 05.10.2015 / 22:20

1 resposta

10

Você nem precisa de um script. Se você estiver usando o bash, você pode ativar extglob e fornecer padrões negativos:

$ 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

Como explicado em 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

Com zsh , o equivalente é:

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

Se você ainda quiser escrever um script para isso, apenas concatene os argumentos que você deu, mas não use curingas ( * ), deixe o script adicioná-los (graças ao @Helios por sugerir uma versão mais simples) :

#!/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})
    
por terdon 05.10.2015 / 22:59