Excluindo todos os arquivos em uma pasta, exceto os arquivos X, Y e Z

17

Eu tenho muitos arquivos e pastas em uma pasta específica e quero excluir todos eles; no entanto, eu queria manter os arquivos X, Y e Z.

Existe uma maneira de fazer algo como: rm * | but NOT grep | X or Y or Z

Amit
fonte
Presumo que posso usar alguma expressão regular lá que fará isso?
11222 Amit

Respostas:

16

Em vez de usar rm, pode ser mais fácil usar o find . Um comando como esse excluiria tudo, exceto um arquivo chamado exatamente 'arquivo'

find . \! -name 'file' -delete

Muitas versões do devem poder suportar globbing e correspondência de expressão regular.

Você também pode canalizar a saída de find para rm também

find . \! -name '*pattern*' -print0 | xargs --null rm 
Zoredache
fonte
3
E isso permite que você veja exatamente quais arquivos serão excluídos removendo os -deletearquivos e quais serão salvos removendo -deletee \!.
Shawn J. Goff
1
cuidado, findé recursivo! para que todos os subdiretórios de arquivos que não correspondam ao ' padrão ' sejam excluídos também
Alexandre Holden Daly
O caminho via xargs precisa de -thth, para impedir a tentativa de excluir diretórios antes dos arquivos incluídos neles. No entanto, acho que o rm também não removerá os diretórios.
usuário desconhecido
9

Usando zsh, with setopt EXTENDED_GLOB, usando o ~operador ( exceto )

rm -- *~(x|y|z)

ou ^operador (negação):

rm -- ^(x|y|z)

Mas você provavelmente deve mover os arquivos para outro lugar e excluir tudo. É muito mais seguro em termos de deslizamentos de dedos, como pressionar Enter muito cedo.

wnoise
fonte
5

Versões posteriores do bash têm a extglobopção de shell que fornece uma sintaxe para fazer o que você deseja (verifique sua página de manual em "Expansão do nome do caminho" para ver se a versão instalada possui):

$ shopt -s extglob  # turn on extended globbing
$ rm !(X|Y|Z)

Para testar, sugiro que você primeiro substitua rmpor echopara ver se a lista de arquivos a serem excluídos é o que você espera.

camh
fonte
5
ls -1 | grep -v "^[XYZ]$" # | xargs rm -r

Atenção: Execute o comando e, se os arquivos a serem excluídos forem os corretos, execute-o novamente e exclua o caractere de hash "#".

Se os nomes dos arquivos forem mais complicados, faça isso.

ls -1 | egrep -v "^file1$|^filename2$|^f1le$" # | xargs rm -r

Novamente, primeiro observe os resultados e remova o sinal de hash.

Esta versão - como sugerido nos comentários - salva alguns caracteres e parece um pouco mais clara.

ls -1 | egrep -v "^(file1|filename2|f1le)$" # | xargs rm -r
ddeimeke
fonte
Uma edição sugerida por ddeimeke é alterar o egrepargumento para"^(file1|filename2|f1le)$"
Michael Mrozek
Se você tiver três arquivos a, be a bo primeiro programa for excluído - se você colocar ab na parte grep: "^[ab]$" ae, bmas não a b, oponha-se apenas às suas intenções. O segundo comando fará o mesmo. E o terceiro também. Você não deve usar 'ls' em scripts, com exceções muito, muito raras. Apenas não faça isso.
desconhecido utilizador
3

Mova os arquivos que você deseja manter longe. Suba um nível, exclua a pasta. Recrie a pasta e mova esses arquivos de volta.

alex
fonte
Eu me pergunto por que o menos? .. Na verdade, é mais fácil e mais seguro do que qualquer coisa proposta por outros: você simplesmente não consegue se acertar com um pé, pressionando um caractere especial no nome do arquivo.
11111 alex
a) Você move seu arquivo X um diretório para cima, onde existe um arquivo X - excluído silenciosamente, desaparecido. b) Você está no diretório superior, onde não existe 'up'. c) Você está em sua casa e não tem permissão para escrever em / home. Se você colocar seu conselho em um script, testá-lo sem problemas e usá-lo em tal situação - peng!
usuário desconhecido
2
a) Ei, eu disse 'mover arquivos para um nível acima '? Eu disse para afastá-los. b) Então você está tentando remover todos os arquivos /, hein? Não é muito prático. c) Tentar remover todos os arquivos do seu $HOMEcomputador também não é prático.
alex
Você está certo, me desculpe.
desconhecido utilizador
0

Isto é o que eu configurei como um script .sh para um gancho de logout do OSX / MacOS, funciona bem o suficiente.

#! /bin/bash
for dir in /PathToFolder/*
 do
    if [ ! "$dir" = "/PathToFolder/FolderToKeep1" ] && [ ! "$dir" = "/PathToFolder/FolderToKeep2" ] && [ ! "$dir" = "/PathToFolder/FolderToKeep3" ] && [ ! "$dir" = "/PathToFolder/FolderToKeep4" ] && [ ! "$dir" = "/PathToFolder/FolderToKeep5" ] && [ ! "$dir" = "/PathToFolder/FolderToKeep6" ] ; then 
      echo ${dir}
      sudo rm -R $dir user
      dscl . -delete $dir
    fi 
  done

exit 0
ICMP
fonte
0

Com o GNU-find, você pode usar a opção -delete, que remove os diretórios, se vazios também:

 find tmp -not -name X -not -name Y -not -name Z -delete 
Usuário desconhecido
fonte
Se X, Y ou Z for um diretório, isso também excluirá os arquivos dentro deles. find tmp -maxdepth 1 -not -name X -not -name Y -not -name Z -deleteé uma maneira de contornar isso.
Gilles 'SO- stop be evil'
Como as pastas no Unix são arquivos (qualquer coisa é um arquivo), talvez seja isso que se destina. A pergunta diz explicitamente: "Eu tenho muitos arquivos e pastas em uma pasta específica e quero excluir todos eles;" - e se você deseja excluir Y, talvez você saiba se Y é um diretório ou não.
desconhecido utilizador
Isso também será excluído tmpse não houver arquivos X/ Y/ Z. Nota !como o equivalente padrão de GNU do -not( -deletetambém é uma extensão GNU)
Stéphane Chazelas
@ StéphaneChazelas: A partir da pergunta, a exclusão de pastas (todas elas) é o que foi solicitado. Como o estrondo precisa ser mascarado, prefiro digitar -not. Pode depender do layout do teclado alemão, onde a Barra Invertida precisa do Alt-Gr.
usuário desconhecido