Questão Como apagar todos os arquivos em um diretório, exceto alguns?


Eu preciso excluir todos os arquivos em um diretório, mas excluir alguns deles. Por exemplo, em um diretório com os arquivos a b c ... z, Preciso excluir todos, exceto para u e p. Existe uma maneira fácil de fazer isso?


119


origem


As respostas abaixo são muito melhores, mas você pode apenas fazer com que os arquivos sejam salvos somente para leitura, deletar todos e então alterá-los de volta para suas permissões originais (contanto que você não use rm -f). Você teria que saber quais permissões restaurar e você teria que saber que nada precisava de acesso de gravação para eles durante o processo. É por isso que as outras respostas são melhores. - Joe
Se você também quiser excluir arquivos ocultos, execute shopt -s dotglob antes de correr rm (...).


Respostas:


O que eu faço nesses casos é digitar

rm *

Então eu pressiono Ctrl+X,* para expandir  * em todos os nomes de arquivos visíveis.

Então eu posso apenas remover os dois arquivos que eu gosto de manter na lista e finalmente executar a linha de comando.


108



Eu acho que isso funciona apenas enquanto a lista de arquivos que * expande também não está ficando muito longo. : -} - Frerich Raabe
Esc seguido por * também expandirá o "*". - slowpoison
@SantoshKumar: Isso não faz sentido para mim. A expansão sempre funcionará, não depende de qual comando você deseja usar depois. - Der Hochstapler
@OliverSalzburg Desculpe, a combinação é um pouco confusa. Eu acho que você deveria escrever como Ctrl + Shift + x + * - Santosh Kumar
@SantoshKumar: Mas essa não é a combinação. - Der Hochstapler


Para rm todos exceto u,p no bash apenas digite:

rm !(u|p)

Isso requer que a seguinte opção seja definida:

shopt -s extglob

Ver mais: glob - Wiki de Greg


143



você deve ter 'extglobbing' ativo: shopt -s extglob - sparkie
Você precisa shopt -s extglob, @Um tiro. Além disso, são apenas arquivos, não diretórios, e é por isso que eu removi o -rf opções em seu comando. - slhck
Se você precisa excluir um arquivo de uma seleção de arquivos, tente isto: rm !(index).html. Isso excluirá todos os arquivos terminados em ".html", com exceção de "index.html". - mzuther


Você pode usar find

find . ! -name u ! -name p -maxdepth 1 -type f -delete
  • ! nega a próxima expressão
  • -name especifica um nome de arquivo
  • -maxdepth 1 fará com que o processo de localização apenas o diretório especificado (find por padrão atravessa diretórios)
  • -type f processará apenas arquivos (e não por exemplo diretórios)
  • -delete irá apagar os arquivos

Você pode então ajustar as condições olhando para o página do homem de encontrar

Atualizar

  • Tenha em mente que a ordem dos elementos das expressões é significativa (veja a documentação)
  • Teste seu comando primeiro usando -print ao invés de -delete

    find . ! -name u ! -name p -maxdepth 1 -type f -print
    

67



@Dennis Obrigado atualizei a resposta - Matteo
ordem de predicados é crítica aqui. Se alguém colocar -delete logo após . será desastre (apagará todos os arquivos no CWD) - Michał Šrajer
Isto poderia ser escrito de forma mais compacta find . -maxdepth 1 -type f -name '[^up]' -delete - kojiro
@kojiro sim, mas apenas para arquivos que são apenas uma letra. Com nomes mais complexos, o regex pode ser uma bagunça. - Matteo
find é meu melhor amigo, especialmente quando há muitos arquivos para glob - Terence Johnson


Simples:

mv os arquivos que você quer em um diretório superior, rm o diretório e depois mv eles de volta.


42



Claro, mv-los para um diretório maior. Tente não alterá-los para um subdiretório que você está excluindo ... - Konerak
@Konerak: rm sem -r não irá remover subdiretórios. - reinierpost
Isso sobrescreverá arquivos com o mesmo nome no diretório de destino - Matteo
Eu estou downvoting isso porque, embora possa ser útil, também é não-atômica e efetivamente remove todos os arquivos do diretório durante um curto período de tempo; isso não seria aceitável se, por exemplo, os arquivos estivessem sendo compartilhados na rede. - sam hocevar


Um pouco semelhante ao esta resposta mas não são necessárias opções especiais, tanto quanto eu sei o seguinte é a funcionalidade "antiga" suportada por qualquer shell de shell (vagamente) / bin / sh (por exemplo, bash, zsh, ksh, etc)

rm [^up]

15



Isso funciona para os nomes de arquivo 1-char. Para nomes mais longos, a resposta de Sparkie é melhor. - glenn jackman
O que estaria errado com rm [^up]*? Eu faço coisas semelhantes com bastante frequência. - Michael Kjörling
@ MichaelKjörling - isso excluiria todos os arquivos que começam com u ou p, não apenas aqueles com os nomes u e p. Eu acho que o OP (@Ashot) significava a-z e u, p, etc. simbolicamente e não literalmente. - Sudipta Chatterjee
@HobbesofCalvin Isso excluiria todos os arquivos não começando com u ou p, não aqueles que começam com eles. - rjmunro
@rjmunro - obrigado, perdi aquele! :) - Sudipta Chatterjee


Fazendo isso sem encontrar:

ls | grep -v '(u|p)' | xargs rm

(Edit: "u" e "v", como em outros lugares aqui, estão sendo usados ​​como versões genéricas de expressões regulares inteiras. Obviamente, você vai querer ter cuidado para ancorar seus regexes para evitar combinar muitas coisas.)

Você definitivamente vai querer um roteiro se for fazer muito disso, como outros sugeriram.


11



grep não suportará regexpt estendido por padrão: use -E ou egrep - Matteo
isso excluirá qualquer arquivo que contenha u ou um p - Matteo
@Matteo Não, não vai. O grep não está usando os arquivos, está mostrando a saída do comando ls. Você está pensando em algo como grep -L (u|p)' * | xargs rm Onde -L significa lista de nomes de arquivos que não contêm uma correspondência. - rjmunro
Ah, você quer dizer qualquer arquivo que o nome contenha u ou p, nenhum arquivo contendo um u ou um p. Está correto. Você pode consertar usando egrep -v '^(u|p)$' - rjmunro
Aqui está remover tudo, exceto esses jogos! ls | grep -v 'vuze\|progs' | xargs rm -rf - Nick


GLOBIGNORE pega uma lista separada por dois pontos

GLOBIGNORE=u:p
rm *

5



Isso não funciona no meu shell (GNU bash 4.1.5 (1)). Certifique-se de testá-lo primeiro com algo um pouco menos prejudicial do que rm ou em um diretório de teste! - Michael Kjörling


Em zsh:

setopt extended_glob  # probably in your .zshrc

então

rm ^(u|p)

ou

rm *~(u|p)

O segundo vai funcionar mesmo se você tiver ^ dentro $histchars para substituição de história e, claro, você pode colocar um globo arbitrário antes do ~.


5





De volta à era do disquete, eu tinha um dos executável chamado "Excepto" que moveria as coisas para fora do diretório atual temporariamente e executaria um comando, assim você poderia dizer:

exceto * .txt del *. *

para apagar tudo menos seus arquivos de texto.

Isso seria uma coisa muito trivial para implementar como um script de shell e se esse é o tipo de coisa que você provavelmente fará mais do que duas vezes, parece que seria uma boa ideia.


3



Isso me lembrou a mesma coisa. Mas temporariamente sair da pasta pode não ser uma boa ideia na era da multitarefa :) - Sedat Kapanoglu