Como excluir todos os arquivos em um diretório, exceto alguns?
123
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 ue p. Existe uma maneira fácil de fazer isso?
As respostas abaixo são muito melhores, mas você pode criar os arquivos para salvar somente leitura, excluir tudo e alterá-los para as permissões originais (desde que você não use rm -f). Você precisaria saber quais permissões restaurar e saber que nada precisava de acesso de gravação a elas durante o processo. É por isso que as outras respostas são melhores.
21413 Joe
1
Se você também deseja excluir arquivos ocultos, execute shopt -s dotglobantes de executar rm (...).
Respostas:
108
O que faço nesses casos é digitar
rm *
Em seguida, pressiono Ctrl+ X, *para expandir* para todos os nomes de arquivos visíveis.
Depois, basta remover os dois arquivos que gosto de manter da lista e finalmente executar a linha de comando.
você deve ter 'extglobbing' ativo: shopt -s extglob
sparkie
18
Você precisa shopt -s extglob, @Ashot. Além disso, são apenas arquivos, não diretórios, e é por isso que removi as -rfopções do seu comando.
slhck
4
Se você precisar excluir um arquivo de uma seleção de arquivos, tente o seguinte: rm !(index).html. Isso excluirá todos os arquivos que terminam em ".html", com a exceção de "index.html".
Mzuther
71
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 1fará do processo find apenas o diretório especificado ( findpor padrão, percorre os diretórios)
-type f processará apenas arquivos (e não por exemplo diretórios)
Offcourse, mova-os para um diretório mais alto. Tente não mv-los para um subdiretório que você está excluindo ...
Konerak
@ Konerak: rmsem -r, não removerá subdiretórios.
Reinierpost
11
Isto irá sobrescrever arquivos com o mesmo nome no diretório de destino
Matteo
7
Estou com o voto negativo porque, embora possa ser útil, ele também não é atômico e remove efetivamente 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
15
Um pouco semelhante a esta resposta, mas nenhuma opção especial é necessária, até onde eu sei o seguinte é uma funcionalidade "antiga" suportada por qualquer shell (vagamente) / bin / sh (por exemplo, bash, zsh, ksh, etc)
Isso funciona para os nomes de arquivos de 1 caractere. Para nomes mais longos, a resposta do sparkie é melhor.
glenn jackman
3
O que haveria de errado rm [^up]*? Faço coisas semelhantes com bastante frequência.
um CVn em
3
@ MichaelKjörling - isso excluiria todos os arquivos iniciados com u ou p, não apenas aqueles com os nomes u e p. Eu acho que o OP (@Ashot) significava az e u, p, etc. simbolicamente e não literalmente.
Sudipta Chatterjee
4
@HobbesofCalvin Isso excluiria todos os arquivos que não começam com u ou p, e não aqueles que começam com eles.
Rjmunro
@rjmunro - obrigado, perdi essa! :)
Sudipta Chatterjee
11
Fazendo isso sem encontrar:
ls | grep -v '(u|p)'| xargs rm
(Edite: "u" e "v", como em outros lugares aqui, estão sendo usados como versões genéricas de regexes inteiras. Obviamente, você deve ter cuidado para ancorar suas regexes para evitar a correspondência de muitas coisas.)
Você definitivamente vai querer um script se estiver fazendo muito disso, como outros sugeriram.
O grep não manipula regexpt estendido por padrão: use -Eoregrep
Matteo
2
isso excluirá qualquer arquivo que contenha um uou ump
Matteo
@ Matteo Não, não vai. O grep não está cumprimentando os arquivos, está cumprindo a saída do comando ls. Você está pensando em algo como grep -L (u|p)' * | xargs rmwhere -Lsignifica que os nomes de arquivos da lista não contêm uma correspondência.
Rjmunro
4
Ah, você quer dizer qualquer arquivo cujo nome contenha uou pnão qualquer arquivo que contenha a uou a p. Está correto. Você pode corrigir usandoegrep -v '^(u|p)$'
rjmunro
1
Aqui está remover tudo, exceto essas correspondências! ls | grep -v 'vuze\|progs' | xargs rm -rf
Nick
6
No zsh:
setopt extended_glob # probably in your .zshrc
então
rm ^(u|p)
ou
rm *~(u|p)
A segunda vai funcionar mesmo se você tiver ^em $histcharspara substituição história, e, claro, você pode colocar um glob arbitrária antes da ~.
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 querm ou em um diretório de testes!
um CVn em
3
Na era do disquete, eu tinha um executável DOS chamado "Except", que movia temporariamente as coisas para fora do diretório atual e executava um comando, para que você pudesse dizer:
exceto * .txt del *. *
para excluir tudo, menos seus arquivos de texto.
Isso seria uma coisa bastante trivial para implementar como um script de shell e, se esse é o tipo de coisa que você provavelmente fará mais do que o dobro, parece que seria uma boa idéia.
Para aqueles que preferem especificar padrões de exclusão complexos arbitrários (abrangendo todos os nomes de arquivos afetados) em um estilo completo de eMexs de regexp, posix-awk ou posix-extended (consulte a página de manual de localização), eu recomendaria este. Exclui ue pno dir atual neste exemplo. Isso pode ser útil para scripts.
Você precisa especificar um diretório antes da expressão (`find. -Regextype ...).
Matteo
-regextypesó funciona em versões GNU
Matteo
Não - minha versão find (aperto debian) definitivamente não requer um diretório explícito antes de a expressão se o diretório atual deve ser usado
sparkie
@sparke: isso só funciona em implementações GNU
Matteo
@parkpark: não definir o diretório (primeiro parâmetro) para findé uma extensão de findcomando GNU . O mesmo se aplica à -regextypeopção. Além disso, seu comando excluirá os arquivos nos subdiretórios também, enquanto a pergunta original claramente perguntou sobre os arquivos em um diretório.
Mikko Rantalainen
1
Eu sempre uso:
rm [a-o,q-t,v-z]*
Isso permitirá que você defina quão granular você deseja torná-lo. Portanto, se você deseja excluir os arquivos a e z, pode usar:
for FILE in./*;doif[[ $FILE !=./u*]]||[[ $FILE !=./p*]];then rm $FILE;fi;done;
É meio demorado e não sei se você poderia transformá-lo facilmente em uma função que poderia acomodar facilmente um número arbitrário de argumentos, mas funciona bem.
shopt -s dotglob
antes de executarrm (...)
.Respostas:
O que faço nesses casos é digitar
Em seguida, pressiono Ctrl+ X, *para expandir
*
para todos os nomes de arquivos visíveis.Depois, basta remover os dois arquivos que gosto de manter da lista e finalmente executar a linha de comando.
fonte
*
também se expande não está ficando muito longa. : -}Ctrl
+Shift
+x
+*
Para
rm
todos, excetou,p
no bash, basta digitar:Isso requer que a seguinte opção seja configurada:
Ver mais: glob - Wiki de Greg
fonte
shopt -s extglob
, @Ashot. Além disso, são apenas arquivos, não diretórios, e é por isso que removi as-rf
opções do seu comando.rm !(index).html
. Isso excluirá todos os arquivos que terminam em ".html", com a exceção de "index.html".Você pode usar
find
!
nega a próxima expressão-name
especifica um nome de arquivo-maxdepth 1
fará do processo find apenas o diretório especificado (find
por padrão, percorre os diretórios)-type f
processará apenas arquivos (e não por exemplo diretórios)-delete
excluirá os arquivosVocê pode ajustar as condições na página de manual do find
Atualizar
Teste seu comando primeiro usando em
-print
vez de-delete
fonte
-delete
logo após.
será desastre (irá apagar todos os arquivos em CWD)find . -maxdepth 1 -type f -name '[^up]' -delete
find
é meu melhor amigo, especialmente quando há muitos arquivos para globSimples:
mv
os arquivos que você deseja em um diretório superior,rm
o diretório e depoismv
os retorna.fonte
rm
sem-r
, não removerá subdiretórios.Um pouco semelhante a esta resposta, mas nenhuma opção especial é necessária, até onde eu sei o seguinte é uma funcionalidade "antiga" suportada por qualquer shell (vagamente) / bin / sh (por exemplo, bash, zsh, ksh, etc)
fonte
rm [^up]*
? Faço coisas semelhantes com bastante frequência.Fazendo isso sem encontrar:
(Edite: "u" e "v", como em outros lugares aqui, estão sendo usados como versões genéricas de regexes inteiras. Obviamente, você deve ter cuidado para ancorar suas regexes para evitar a correspondência de muitas coisas.)
Você definitivamente vai querer um script se estiver fazendo muito disso, como outros sugeriram.
fonte
-E
oregrep
u
ou ump
grep -L (u|p)' * | xargs rm
where-L
significa que os nomes de arquivos da lista não contêm uma correspondência.u
oup
não qualquer arquivo que contenha au
ou ap
. Está correto. Você pode corrigir usandoegrep -v '^(u|p)$'
ls | grep -v 'vuze\|progs' | xargs rm -rf
No zsh:
então
ou
A segunda vai funcionar mesmo se você tiver
^
em$histchars
para substituição história, e, claro, você pode colocar um glob arbitrária antes da~
.fonte
GLOBIGNORE utiliza uma lista separada por dois pontos
fonte
rm
ou em um diretório de testes!Na era do disquete, eu tinha um executável DOS chamado "Except", que movia temporariamente as coisas para fora do diretório atual e executava um comando, para que você pudesse dizer:
para excluir tudo, menos seus arquivos de texto.
Isso seria uma coisa bastante trivial para implementar como um script de shell e, se esse é o tipo de coisa que você provavelmente fará mais do que o dobro, parece que seria uma boa idéia.
fonte
Isso excluirá todos os arquivos, exceto u e p no unix
fonte
Para aqueles que preferem especificar padrões de exclusão complexos arbitrários (abrangendo todos os nomes de arquivos afetados) em um estilo completo de eMexs de regexp, posix-awk ou posix-extended (consulte a página de manual de localização), eu recomendaria este. Exclui
u
ep
no dir atual neste exemplo. Isso pode ser útil para scripts.fonte
-regextype
só funciona em versões GNUfind
é uma extensão defind
comando GNU . O mesmo se aplica à-regextype
opção. Além disso, seu comando excluirá os arquivos nos subdiretórios também, enquanto a pergunta original claramente perguntou sobre os arquivos em um diretório.Eu sempre uso:
Isso permitirá que você defina quão granular você deseja torná-lo. Portanto, se você deseja excluir os arquivos a e z, pode usar:
fonte
Ainda outra versão usando
xargs
:Observe que
xargs -I
é necessário para manipular nomes de arquivos, incluindo espaços corretamente.fonte
Ainda outra:
É meio demorado e não sei se você poderia transformá-lo facilmente em uma função que poderia acomodar facilmente um número arbitrário de argumentos, mas funciona bem.
E é pura bondade.
fonte
Aqui está outra variante. Você pode digitar:
ou:
Então
rm
, você deverá confirmar a exclusão de cada arquivo.fonte
Usar:
para excluir todos os arquivos, incluindo os diretórios, exceto os arquivos u, pe .ext.
fonte
Uma maneira simples e difícil de estragar: digamos que você queira excluir tudo, exceto * .pdf:
fonte