Questão redirecionamento de argumentos xargs


Este parece ser um problema trivial, mas a solução me ilude com tanta cautela.

Eu quero limpar muitos arquivos de texto; arquivos de log. Razão? Para economizar espaço em disco.

Com um arquivo de texto, isso é tão trivial quanto echo '' > path/to/file.txt

No entanto, os arquivos são muitos. Eu recorri a usar find e xargs. Mas eu não sei como se locomover "redirecionamento de entrada".

eu tentei find . -name <regex> | xargs -I target echo '' > target e echo '' > { find . -name <regex> | xargs -I target target }; nenhum funcionou

Eu não sou bem versado em shell-script, qualquer ajuda é apreciada.

Obrigado.


4


origem




Respostas:


O que você fez em ambos os exemplos é colocar o > onde o atual shell pode vê-lo, então o redirecionamento está sendo feito apenas uma vez, antes dos comandos find e xargs serem executados. Esse é o seu primeiro problema.

Seu segundo problema é que, se você citar o > de modo que é passado através de xargs, ainda não vai funcionar porque xargs não passa seu comando através de um shell a menos que você peça.

Seu terceiro problema é que se você disser ao xargs para usar um shell para executar o comando, o shell fará a coisa errada se algum nome de arquivo contiver caracteres engraçados. (Também xargs faz a coisa errada com personagens engraçados em si, mas isso é consertável com -0.)

Outros problemas, com os quais você talvez não se importe, incluem:

  • eco '' não cria um arquivo vazio, mas um arquivo contendo uma nova linha.
  • a -name opção leva um glob, não um regex.
  • você pode querer adicionar -type f apenas no caso de quaisquer diretórios corresponderem ao glob.

Aqui está uma versão parcialmente corrigida do comando:

find . -name '*thisisaglob*' -type f -print0 |
xargs -0 -I target sh -c ': > target'

Isso corrige a maioria dos problemas que mencionei. Ainda permanece o problema do shell interpretar erroneamente um nome de arquivo contendo metacaracteres de shell. Para corrigir isso, você teria que dar o nome do arquivo para o shell como um parâmetro em vez de como parte do -c comando. Isso ficaria assim:

find . -name '*thisisaglob*' -type f -print0 |
xargs -0 -I target sh -c ': > "$1"' fnord target

O "fnord" é um marcador de posição. Se torna $0 que não precisamos.

Agora, tendo cumprido o objetivo de usar xargs e redirecionamento juntos com segurança, mostrarei a você como alcançar seu objetivo usando nenhum deles.

find . -name '*thisisaglob*' -type f -exec truncate -s 0 '{}' +

Isso requer o truncate comando, que é parte do GNU coreutils e não um utilitário padrão unix, por isso é menos portátil, mas muito mais fácil de ler, não é?


9



Mesmo que isso não seja a resposta, é altamente informativo. No entanto, isso funcionou. Infelizmente, só posso votar uma vez. Obrigado!! - iGbanam


Embora a resposta de Alan Curry seja completa, precisa e muito bem informada, tenho uma pergunta. Por que você quer que os arquivos continuem existindo, mesmo vazios?

Minha recomendação natural seria:

find . -name <glob> -print0 | xargs -0 rm

Se você precisava que os arquivos existissem por algum motivo, você poderia fazer uma série de comandos:

find . -name <glob> -print0 | tee /tmp/filelist | xargs -0 rm
cat /tmp/filelist | xargs -0 touch

Se você simplesmente quisesse compactar os arquivos (por exemplo, se eles fossem principalmente informações redundantes / repetitivas, mas você quisesse economizar espaço e manter os arquivos), você pode tentar:

find . -name <glob> -print0 | xargs -0 tar -xzf /tmp/logfiles.tgz

2



Eles são aplicativos de trilhos. Eu preferiria manter os arquivos para que o framework saiba onde colocar os logs. - iGbanam


Se você tem o GNU Parallel http://www.gnu.org/software/parallel/ instalado você pode fazer isso:

find . -name '*thisisaglob*' -type f | parallel '>'

Você pode instalar o GNU Parallel simplesmente por:

wget http://git.savannah.gnu.org/cgit/parallel.git/plain/src/parallel
chmod 755 parallel
cp parallel sem

Assista aos vídeos de introdução do GNU Parallel para saber mais: https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1


0