O que você fez em ambos os exemplos é colocar o >
onde o shell atual pode vê-lo, então o redirecionamento está sendo feito apenas uma vez, antes que os comandos find e xargs sejam executados. Esse é o seu primeiro problema.
Seu segundo problema é que, se você citar o >
para que ele seja passado para xargs
, ele ainda não funcionará porque xargs
não passa seu comando por meio de um shell, a menos que você o solicite.
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 pode ser corrigido com -0
.)
Outros problemas, com os quais você talvez não se importe, incluem:
- echo
''
não cria um arquivo vazio, mas um arquivo que contém uma nova linha. - a opção
-name
usa glob e não regex. - talvez você queira adicionar
-type f
apenas no caso de qualquer diretório corresponder 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 ao shell como um parâmetro em vez de como parte do comando -c
. 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. Torna-se $0
do qual não precisamos.
Agora que atingimos o objetivo de usar o xargs e o redirecionamento juntos com segurança, mostrarei como alcançar seu objetivo usando nenhum deles.
find . -name '*thisisaglob*' -type f -exec truncate -s 0 '{}' +
Isso requer o comando truncate
, que é parte do GNU coreutils e não um utilitário padrão do unix, por isso é menos portável, mas muito mais fácil de ler, não é?