Remova todos os arquivos * .mp4 e * .zip, mas alguns arquivos

1

Em um dos meus programas eu chamo um comando bash para remover todos os arquivos no diretório, mas alguns:

bash -c
shopt -s extglob
shopt -s nullglob
rm /path/to/directory/!("file1" | "file2")

O que eu entendo significa "Use bash neste comando, use o padrão estendido, remova todos os arquivos, exceto aqueles"

Funciona bem, mas apaga todos os arquivos, exceto os colocados no comando.

O que eu gostaria é remover todos os arquivos .mp4 e .zip do diretório, mas os que eu coloquei no comando.

Eu acho que vou ter que adicionar * .mp4 e * .zip em algum lugar no comando, mas não tenho idéia de onde.

EDIT: Para maior clareza, o que eu preciso é "Exclua todos os arquivos .mp4 e .zip, mas mantenha esses"

    
por DrakaSAN 15.11.2013 / 10:36

3 respostas

1

O padrão !("file1" | "file2") corresponde a qualquer arquivo, exceto file1␣ ou ␣file2 , em que é um espaço. A maneira como você citou é enganosa: é equivalente a !(file1 | file2) ou !("file1 "|" file2 ) '.

Não há como bash combinar um padrão negativo com um padrão positivo para dizer "todos esses, exceto aqueles". Em zsh, você pode escrever

setopt extended_glob
rm /path/to/directory/*.(mp4|zip)~(keep*|1234.zip)

para remover this.mp4 e that.zip , mas não keep-this.mp4 ou 1234.zip .

No bash, você pode definir a GLOBIGNORE variable para excluir certos padrões de todos os jogos.

shopt -s extglob
GLOBIGNORE='keep*:1234.zip'
rm /path/to/directory/*.(mp4|zip)
unset GLOBIGNORE

Como alternativa, você pode usar find , que permite criar expressões booleanas arbitrariamente complexas.

find /path/to/directory \( -name '*.mp4' -o -name '*.zip' \) ! -name 'keep*' ! -name '1234.zip' -delete

Observe que find recorre a subdiretórios. Se isso não for desejado, adicione -maxdepth 1 após /path/to/directory .

Se o seu find não entender -maxdepth (é comum, mas não padrão), use -type d -prune -o . Se seu find não entender -delete (mesmo comentário), use -exec rm {} + .

    
por 18.11.2013 / 00:10
1

Existem várias maneiras:

  • Use find (portável, pois não precisa de shell específico [bash])
find . -maxdepth 1 ! -name "exclude" -delete

ou no caso de você ter vários padrões:

find . -maxdepth 1 ! \( -name "exclude" -o -name "exclude2" \) -exec rm -f {} \+
  • Use a variável GLOBIGNORE (apenas bash)
export GLOBIGNORE=exclude:exclude1:mask*

Isso excluirá os arquivos e máscaras mencionados da globalização. Depois disso, você pode especificar rm your_pattern

Você pode experimentar antes com ls

    
por 15.11.2013 / 11:00
0

Eu gostaria de encontrar. No entanto, seu problema são os espaços.

rm /path/to/directory/!("file1" | "file2")

é o mesmo que rm "/path/to/directory/!(file1" "|" "file2)"

não rm "/path/to/directory/!(file1|file2)"

leia as regras de cotação do shell.

    
por 15.11.2013 / 12:41

Tags