exclusão em massa do arquivo

3

Eu gostaria de excluir todos os arquivos txt, xls, pdf em um diretório, assim como seus subdiretórios. Eu gostaria de salvar todo o resto.

find . -type f ! -iname '*.xml$,.png$,.jpeg$,.gif$,' -delete

que parece ter feito isso, mas exclui alguns outros arquivos que eu preciso. Como posso conseguir isso sem excluir mais nada?

    
por user37664 22.04.2013 / 21:16

3 respostas

4

Faça isso:

find . -type f -iname '*.xml' -o -iname '*.png'\
       -o -iname '*.jpeg' -o -iname '*.gif' -delete

Você também pode usar expressões regulares:

find . -type f -iregex '.*\.\(xml\|png\|jpeg\|gif\)$' -delete
    
por 22.04.2013 / 22:02
2

Existem basicamente 4 maneiras de abordar esse problema usando o find.

Método 1 - usando -delete

$ find . -type f -iname '*.xml' -o -iname '*.png'\
       -o -iname '*.jpeg' -o -iname '*.gif' -delete

Como outros mencionaram neste Q & A, esse método é o mais rápido e o de menor uso intensivo de recursos. Citando os documentos on-line :

10.1.6 Using the '-delete' action


The most efficient and secure method of solving this problem is to use the '-delete' action:

 find /var/tmp/stuff -mtime +90 -delete

This alternative is more efficient than any of the -exec' or-execdir' actions, since it entirely avoids the overhead of forking a new process and using exec' to run/bin/rm'. It is also normally more efficient than xargs' for the same reason. The file deletion is performed from the directory containing the entry to be deleted, so the-delete' action has the same security advantages as the '-execdir' action has.

The '-delete' action was introduced by the BSD family of operating systems.

OBSERVAÇÃO: Uma coisa a ter em mente com esta abordagem, o uso de -delete implica também a opção -depth . O que isto significa? Aqui está um exemplo de como -delete pode queimar você se você não for cuidadoso.

Por exemplo, digamos que eu tenha um diretório de trabalho de subversão onde eu queira limpar alguns arquivos, mas deixe seus subdiretórios .svn intactos. Eu poderia usar o seguinte comando para realizar isso:

$ find . -not "(" -name .svn -type d -prune ")" -type f -print
./a.txt

Mas como -delete inclui uma opção -depth , os arquivos que seriam realmente tratados:

$ find . -not "(" -name .svn -type d -prune ")" -type f -print -depth
./.svn/all-wcprops
./.svn/entries
./.svn/format
./.svn/text-base/a.txt.svn-base
./a.txt

Por esse motivo, ao usar -delete , é preciso ter cuidado.

Método 2 - -exec command {} +

$ find . -type f -iname '*.xml' -o -iname '*.png'\
       -o -iname '*.jpeg' -o -iname '*.gif' -exec rm {} \+

Em comparação com o método -delete , esta é provavelmente a melhor opção seguinte, em termos de desempenho & portabilidade entre Unixes. A notação -exec ... {} + funciona da seguinte maneira:

da página man do encontro

This variant of the -exec action runs the specified command on the selected files, but the command line is built by appending each selected file name at the end; the total number of invocations of the command will be much less than the number of matched files. The command line is built in much the same way that xargs builds its command lines. Only one instance of '{}' is allowed within the command. The command is executed in the starting directory.

Portanto, na verdade, esse método funciona de forma semelhante a xargs , mas sem ter que passar por obstáculos de passar a saída de uma descoberta por meio de um canal para xargs .

Método 3 - xargs

$ find . -type f -iname '*.xml' -o -iname '*.png'\
       -o -iname '*.jpeg' -o -iname '*.gif' -print0 | xargs -0 rm -f

O find ... -print0 criará uma lista de arquivos correspondentes aos critérios especificados. Essa lista é então passada pelo pipe para xargs . A opção -print0 coloca um caractere ASCII NUL como um separador entre cada resultado de find. A opção -0 em xargs faz supor que os arquivos que estão sendo passados são separados por caracteres ASCII NUL.

Em comparação com os métodos # 1 e amp; # 2, este terá um desempenho semelhante ao # 2, no entanto, a opção -print0 não é universalmente suportada em todos os Unixes.

Método 4 - -exec command {} \;

$ find . -type f -iname '*.xml' -o -iname '*.png'\
       -o -iname '*.jpeg' -o -iname '*.gif' | exec rm -f {} \;

Em comparação com os 3 primeiros métodos, este é o de menor desempenho. Chama literalmente o comando rm para cada arquivo individual que o comando find encontra.

Considerações adicionais sobre segurança

Uma coisa que pode não ser tão óbvia ao usar qualquer um dos métodos acima é que alguns dos métodos são mais seguros do que os outros. Você provavelmente está dizendo para si mesmo ... segurança? .. que? Aqui está um exemplo.

Assuma sua raiz e execute o seguinte comando:

$ find /var/tmp/somedir -type f -exec rm {} \;
Sem o seu conhecimento, alguém criou maliciosamente um link para o diretório /etc em /var/tmp/somedir . Quando o comando acima for executado, o diretório /etc também será excluído. Esse problema existe com qualquer um dos métodos para excluir arquivos, exceto a opção -delete (método 1).

tl; dr;

A maneira mais rápida e segura de excluir arquivos com a ajuda do find é usar -delete . Usar xargs -0 pode ser semelhante em desempenho, mas não é tão seguro. A ação -delete não é totalmente portátil. A alternativa portátil mais eficiente é -exec ... + , mas isso é inseguro e não é suportado por versões de findutils do GNU anteriores a 4.2.12.

Referências

por 22.04.2013 / 22:31
0

Existe uma pequena imprecisão na resposta do slm .

NOTA & Disclamer : este deve ser um comentário para resposta do slm , mas agora eu não posso fazer comentários ainda.

O exemplo "alguém criou maliciosamente um link" fornecido em Considerações adicionais sobre segurança não é totalmente preciso sobre links físicos Unix e links para Unix.

Para entender a diferença entre os dois, consulte link físico e links simbólicos em Unix ou pesquise no Google.

Para links suaves (o tipo mais usado de qualquer maneira), ambos GNU find e BDS find não seguem links simbólicos, a menos que seja usado um sinalizador específico -L para forçar o link simbólico a seguir. [Veja man find ]

Portanto, este exemplo provavelmente não será um problema, a menos que você force find a seguir os soft links usando o -L flag. Esta é a escolha perigosa, de qualquer maneira.

Para os links físicos, find seguirá o link para outro arquivo , mas observe que o link físico para um outro diretório "provavelmente falhará", conforme veremos em man ln para o% GNUln:

   -d, -F, --directory
          allow the superuser to attempt to hard link directories (note: will probably
          fail due to system restrictions, even for the superuser)

Portanto, provavelmente é impossível criar o link físico para um diretório e find não terá nada a seguir.

Observe que alguns BDS ln implementação não tem uma -d opção.

    
por 10.05.2013 / 11:10

Tags