Recentemente, fui confrontado com a tarefa de excluir todos os arquivos / pastas em um diretório, excluindo aqueles que correspondiam a um padrão específico. Então, criei um comando unix de linha única para fazer o trabalho. Deve ser apenas uma linha? Suponho que não, mas é definitivamente mais legal assim!
Embora o problema seja bastante simples, fiquei um pouco surpreso com a complexidade da minha solução. Aqui está o comando que eu usei; NOTA: esta é uma solução ruim porque não lida com nomes de arquivos contendo caracteres de feed de linha (o que não importava na minha situação).
ls | grep -v PATTERN | xargs -n1 -IREPLACE rm -rf REPLACE
Eu não usei o comando "find" porque não quero recursar em pastas correspondentes a PATTERN. Por exemplo, considere a seguinte estrutura de arquivo:
file_foo.txt
first_dir
|
+--> contents
+--> ...
foo_dir
|
+--> anotherfile.txt
+--> morefiles.log
foo_file.txt
somefile.txt
O uso do padrão "foo" deve remover apenas "first_dir" (e seu conteúdo, é claro) e "somefile.txt" ( não "anotherfile.txt" ou "morefiles.log").
Pergunta, existem maneiras melhores (mais elegantes e corretas) de conseguir isso?
EDIT:
Recentemente, soube que "encontrar" pode ser uma opção melhor :
find * -maxdepth 0 ! -name PATTERN -print0 | xargs -0n1 rm -rf
Esta solução manipula corretamente caminhos contendo caracteres de alimentação de linha.
fonte
Respostas:
Os exemplos a seguir foram
echo
prefixados para que você possa testar os padrões antes de realmente usá-los. Remova oecho
para ativar orm -rf
. Substituarm -ri
para solicitar confirmação.O ksh tem uma extensão de correspondência negativa para o globbing:
A mesma sintaxe está disponível no bash se você definir a
extglob
opção:O zsh tem sua própria sintaxe para isso:
Também pode usar a sintaxe no estilo ksh :
fonte
shopt -s extglob
ao meu arquivo .bashrc, agora é uma linha). Perfeito! Eu prometo um voto positivo assim que minha reputação permitir.Aqui está outra
find
solução. Não tenho certeza se isso tem alguma vantagem real sobre a sua, mas não precisaxargs
e permite a rara possibilidade de que * se expanda para muitos nomes.Eu também adicionei
-type f
para que ele não tentasse excluir diretórios.Atenção:
-delete
é poderoso. Dei a um dos meus arquivos de teste 0 permissões e o comando acima o excluiu sem hesitar.fonte
-delete
por-print
para ver se está encontrando os arquivos que você deseja. Se tudo estiver bom, use o histórico de comandos (por exemplo, pressione o botão para cima) para voltar ao comando anterior para garantir que você esteja trabalhando com os mesmos filtros de localização.find -delete
não removerá diretórios não vazios. Observe também quefind -maxdepth 1
corresponde a "." (diretório atual) que é realmente ruim. Embora eu goste da sua idéia de eliminarxargs
, pode-se usarfind -exec
alternativamente.find * -maxdepth 0 ! -name PATTERN -exec rm -rf '{}' \;
Você pode usar este exemplo de script rebol http://askcodegeneration.com/keep-subversion/, que é muito mais compreensível e que pode gerenciar a interação do usuário, como seleção e confirmação de pasta:
fonte