Eu tive um problema em que queria encontrar o comprimento de cada caminho de um find
comando. Minha primeira tentativa foi executar algo assim:
find . -exec sh -c "echo {} | wc -c" \;
Eu tenho essa idéia desta resposta . (O comando acima não é minha pergunta, estou apenas usando-o como exemplo e é completamente artificial. Além disso, às vezes posso precisar de mais de um pipe.)
Mas quando o executei, houve erros na saída, provavelmente devido a caracteres especiais nos caminhos de saída. Infelizmente, não tenho conhecimento para solucionar quais caminhos causaram o problema e as mensagens de erro não eram informativas. Sem considerar...
Mais tarde, tropecei nesta resposta :
O
find
comando executa o comando diretamente. O comando, incluindo o argumento do nome do arquivo, não será processado pelo shell ou qualquer outra coisa que possa modificar o nome do arquivo. É muito seguro.
Isso parece muito conveniente. Tão conveniente, de fato, que a -exec sh -c ...
"cura" parece pior que a doença.
Então, minha pergunta é: o que devo fazer quando preciso canalizar comandos find
e meus caminhos podem ter caracteres especiais? Existe uma solução genérica para este problema onde eu não tenha que considerar um monte de ressalvas? Estou usando bash.
Nota: Esta é uma pergunta semelhante: qual a melhor forma de enviar a saída de um comando find + exec para um pipeline? A diferença é que não estou necessariamente tentando canalizar a saída para fora do -exec
. ou seja, se find ... -exec ... foo {} | bar \;
é o caminho a seguir, está perfeitamente bem para mim. Estou apenas procurando um caminho genérico de menor resistência, a estrutura do comando não é importante para mim.
Passe o nome do arquivo como um argumento para o script de shell:
ou para vários arquivos por invocação de shell:
Seu comando
inseriria o nome do arquivo como está na linha de comando do shell. Funcionaria apenas para nomes de arquivos que não contêm espaços em branco ou caracteres especiais para o shell. Por exemplo, algo como um
Don't stop me now.mp3
,this&that.txt
causaria problemas. (O primeiro produziria uma string entre aspas não terminada e o segundo iniciariaecho
em segundo plano e tentaria executar um comando chamadothat.txt
.)Por outro lado,
sh -c ... sh {} \;
(ou... {} +
passoufind
o(s) nome(s) do(s) arquivo(s) como argumento(s) distinto(s) para o shell, onde eles estarão disponíveis nos parâmetros posicionais e podem ser usados sem que eles sejam misturados com a sintaxe do shell. ("$1"
para o primeiro,"$@"
para toda a lista. Lembre-se das aspas.)Para o caso de verificar o comprimento do nome do arquivo, você também pode obtê-lo
"${#var}"
no shell, exceto que ele fornece o comprimento em caracteres de acordo com a localidade atual, enquantowc -c
conta bytes .Mesmo que
-exec echo {}
evite o processamento do shell , muitas versões do (s) argumento(s) echo mangle contêm barra invertida ou hífen à esquerda. (E é claro que não canalizawc
como você deseja.)Em vez de executar
wc
para cada nome de caminho, eu usaria um programa projetado para lidar com várias linhas de entrada, também conhecidas como registros:Ou
perl -nle 'print length'
o padrão para bytes, mas não vejo uma maneira de lidar com o-print0
caso para permitir novas linhas.