Como executar um comando para cada arquivo em uma estrutura de diretórios profunda, recursivamente?

7

Eu tenho uma estrutura de diretórios profunda, com um grande número de arquivos (cerca de 1M). Eu gostaria de executar um comando contra cada um. (No meu caso, os arquivos são pngs que eu gostaria de executar optipng contra.)

Eu tentei isso:

find . -name *.png | xargs sudo optipng -o2

mas estou recebendo o erro argument list too long .

Estou assumindo que os xargs devem ser capazes de lidar com isso e que deve haver um problema com minha sintaxe.

    
por UpTheCreek 25.06.2015 / 09:39

3 respostas

7

Faça o exec diretamente com o find e não via xargs.

sudo find . -name '*.png' -exec optipng -o {} +
    
por 25.06.2015 / 09:58
4

Usar o comando sudo as para executar por xargs não está funcionando, como você vê. Tente o contrário:

find . -name '*.png' | sudo xargs optipng -o2

A diferença é que sua versão cria um comando como

 sudo optipng -o2 file1 file2 file3 file4 ......

e o sudo não consegue lidar com tantos parâmetros.

Fazendo o contrário, executa o sudo uma vez, que por sua vez inicia o xargs , que gera um comando como

optipng -o2 file1 file2 file3 file4 ......

e se optipng puder manipular muitos arquivos como parâmetros, isso deve funcionar.

Se isso ainda não funcionar, você terá que usar -exec , como na resposta de Geraint, mas este deve ser seu último recurso.

    
por 25.06.2015 / 09:52
2

Mais uma chance:

find . -name '*.png' | sudo xargs -n x -P y optipng -o2

O qual iniciará uma otimização para x arquivos e y desses processos em paralelo (pode ajudar você a fazer as coisas mais rapidamente se tiver alguns núcleos de sobra). Ter x maior que 10 provavelmente não causará grande impacto no desempenho.

Isso ajudará a manter a lista de argumentos curta. Então, você provavelmente poderia mover sudo para onde você o tinha, mas esse seria apenas outro comando que teria que ser executado para cada lote.

    
por 20.07.2015 / 00:40

Tags