Remova todos os tipos de arquivos, exceto um (ou mais)

20

Eu tenho tentado encontrar um comando para remover todos os arquivos em uma pasta, mas não um tipo de tipo de arquivo. Mas parece que não tenho sorte. O que eu tentei até agora:

set extended_glob
rm !(*.dmg)
# this returns zsh:number expected

rm ./^*.dmg
# this returns no matches found 

A versão do zsh que estou usando é zsh 5.0.2 (x86_64-apple-darwin13.0.1).

Dzung Nguyen
fonte

Respostas:

22

A extended_globopção fornece a própria sintaxe glob estendida do zsh .

setopt extended_glob
rm -- ^*.dmg
rm -- ^*.(dmg|txt)

Você pode definir a ksh_globopção para obter globs ksh . Lembre-se de que, no caso comum em que o padrão negativo é a última coisa na palavra, o zsh pode analisar os parênteses como qualificadores globais (isso não ocorre no modo de emulação do ksh).

setopt ksh_glob
rm -- !(*.dmg|*.txt)
setopt no_bare_glob_qual
rm -- !(*.dmg)
Gilles 'SO- parar de ser mau'
fonte
Isso não parece funcionar. Quando eu executo rm -r secrets/!(directory)ele continua pedindo number expectedou às vezes isso me dáevent not found: directory
CMCDragonkai
@CMCDragonkai "número esperado" indica que você não definiu a ksh_globopção. “Evento não encontrado: diretório” indica que você está executando o bash (que também entende a !(…)sintaxe, mas somente depois shopt -s extglob).
Gilles 'SO- stop be evil' em
Como eu poderia estar executando o bash quando estava no meu shell zsh?
precisa saber é o seguinte
Para mim, setopt ksh_glob; echo !(a|b)funciona enquanto setopt ksh_glob; echo !(a)não ( "número esperado") ...
ThiefMaster
@ThiefMaster Eu tive o mesmo problema. Isso é um bug?
CodeTower
5

Você pode usar em findvez do seu shell:

find . -mindepth 1 -maxdepth 1 ! -name "*.dmg" -delete

De man find:

   ! expr True  if  expr  is false.  This character will also usually need
          protection from interpretation by the shell.
   -name pattern
          Base of file name (the path with the leading directories removed)
          matches shell pattern pattern. 
   -delete
          Delete  files; true if removal succeeded.  If the removal failed,
          an error message is issued.  If -delete fails, find's exit status
          will be nonzero (when  it eventually exits).  Use of -delete 
          automatically turns on the -depth option.

Se você não puder usá-lo findpor qualquer motivo, aqui está uma maneira de fazer isso com zsh(ou outras conchas). zshsendo zsh, provavelmente existe uma maneira mais simples de fazer isso, mas como eu sou um bashcara, é isso que eu criei:

for file in *; do if [[ ! "$file" == *.dmg ]]; then rm $file; fi; done
terdon
fonte
infelizmente, sempre que eu uso o find no meu mac, ele sai da sessão atual do zsh sem aviso prévio. Você tem o mesmo problema? find [Process completed]
Dzung Nguyen
11
@nXqd veja a resposta atualizada para uma maneira de fazê-lo sem find. Sugiro que você publique uma pergunta sobre seu findproblema, mas isso não deve acontecer. Se o fizer, inclua a saída de type -a find.
terdon
11
Mesmo no bash, há uma solução mais simples: rm !(*.dmg)depois shopt -s extglob.
Gilles 'SO- stop be evil'
@terdon obrigado por suas dicas de depuração no shell. sua saída parece estar correta:find is a shell function find is /usr/bin/find
Dzung Nguyen 24/11
@ nXqd que não está correto, não deve ser uma função shell, deve ser apenas /usr/bin/find. Você tem uma função chamada finddefinida em um dos seus arquivos de configuração do bash. Já que você está no OSX, provavelmente é ~/.profile.
terdon
3

Outra maneira de remover arquivos é com find, xargse rm:

find . -mindepth 1 -maxdepth 1 ! -name '*.dmg' -print0 | xargs -0 rm
Dragos Rizescu
fonte