Lista de argumentos muito longa para xargs / exec

2

Estou trabalhando em um servidor CentOS e tenho que me movimentar e agrupar milhões de arquivos. Eu tentei muitas encarnações de algo como o abaixo, mas todos eles falham com uma lista de argumentos muito longo erro.

comando:

find ./ -iname out.* -type f -exec mv {} /home/user/trash
find ./paramsFile.* -exec cat > parameters.txt 

erro:

-bash: /usr/bin/find: Argument list too long
-bash: /bin/cat: Argument list too long

ou

echo ./out.* | xargs -I '{}' mv /home/user/trash
(echo ./paramsFile.* | xargs cat) > parameters.txt  

erro:

xargs: argument line too long
xargs: argument line too long              

O segundo comando também nunca terminou. Eu ouvi algumas coisas sobre globbing, mas não tenho certeza se entendi completamente. Quaisquer sugestões ou sugestões são bem vindas!

    
por ohblahitsme 10.07.2013 / 07:05

3 respostas

4

Você tem vários erros. Você deve escapar do * globbing. Você precisa colocar {} entre aspas (para segurança do nome de arquivo) e terá que finalizar o -exec com \; .

find ./ -iname out.\* -type f -exec mv "{}" /home/user/trash \;
find -name ./paramsFile.\* -exec cat "{}" >> parameters.txt \;

O problema aqui é que * está correspondendo a todos os arquivos em seu diretório, gerando assim o erro. Se find localizar os arquivos em vez do shell globbing, xargs obterá nomes de arquivos individuais que podem ser usados para construir linhas com o tamanho correto.

    
por 10.07.2013 / 07:47
1

Tente isto:

find . -iname 'out.*' -type f -exec mv '{}' /home/user/trash \;
find . -name 'paramsFile.*' -print0 | xargs -0 cat >> parameters.txt

O >> é garantir que várias chamadas de cat (se você tiver realmente um grande número de arquivos) sejam enviadas para o mesmo arquivo, sem sobrescrever o resultado das chamadas anteriores. Além disso, certifique-se de que parameters.txt comece vazio (ou exclua primeiro).

    
por 10.07.2013 / 07:28
0

Eu não tenho uma caixa à mão no momento para dar uma resposta muito boa (isto é, testada), mas eu acho que isso é um bom uso para parallel .

Se bem entendi, seu comando

find ./ -iname out.* -type f -exec mv "{}" /home/user/trash

está fazendo um grande comando:

mv out.1 out.2 out.3 out.4 ... out.10100942 /home/user/trash

Em vez disso, algo como

find ./ -iname out.* -type f | parallel mv "{}" /home/user/trash

executará milhões de comandos menores:

mv out.1 /home/user/trash
mv out.2 /home/user/trash
...

Você pode querer examinar algumas das opções de parallel , especificamente -j e -i para que você não sobrecarregue seu servidor inesperadamente.

PS. Siga o conselho de @ Bernhard, sempre que você usar uma variável de shell, especialmente para a entrada do usuário, cite-a! Do "{}" não {} .

    
por 10.07.2013 / 08:39