Quero fazer o seguinte:
- Encontre um conjunto específico de arquivos com o
find
comando; - Para qualquer arquivo encontrado, coloque a saída correspondente da
-printf
opção em uma variável chamadastr
e passe-a para o Gawk (e não imprima/use essa saída em nenhum outro lugar); - Execute um programa Gawk para o arquivo correspondente. O conteúdo da
str
variável correspondente deve estar disponível no programa.
Por exemplo, eu tenho o diretório chamado /d/ir
. Ele contém dois arquivos, file1.txt
e file2.txt
. Os arquivos estão na codificação UTF-8. O arquivo cujo nome é file1.txt
contém as duas linhas de texto a seguir:
A
BC
O tamanho do arquivo é 4 bytes.
O arquivo cujo nome é file2.txt
contém as três linhas de texto a seguir:
D
EF
GHI
O tamanho do arquivo é 8 bytes.
Quero imprimir todas essas linhas, anexando o conteúdo correspondente de str
(nome do arquivo, tamanho do arquivo) a cada linha. Portanto, a saída esperada é
A;d/ir/file1.txt,4
BC;d/ir/file1.txt,4
D;d/ir/file2.txt,8
EF;d/ir/file2.txt,8
GHI;d/ir/file2.txt,8
Tentei o seguinte comando:
LC_ALL=en_US.utf8; find "/d/ir" -name "file*.txt" -type f -printf "%p,%s" -execdir gawk -v str="$7" '{
print($0 ";" str)
}' "{}" \+
(Aqui eu esperava que $7
, sendo um parâmetro posicional , se referisse a "%p,%s"
) Mas ele não imprime a saída esperada: ele mostra duas saídas de -printf
(o que eu não quero que aconteça), depois cinco linhas sem os dados necessários de str
.
Qual é o comando correto que resolve o problema? Observe que não quero que as saídas da -printf
opção sejam mostradas/impressas fora do contexto do Gawk: quero apenas passá-las para o Gawk para que somente o programa Gawk saiba como usá-las. Se o programa Gawk não as usar, elas não devem ser mostradas em lugar nenhum.
Como o comando será usado para muitos arquivos, a maximização do desempenho e a minimização do consumo de memória são importantes.
O que é impresso pelo seu
find
comando não é passado paragawk
. Se você quiser passar algo paragawk
o canal de saída defind
paragawk
e deixargawk
o processo processar, provavelmente seria melhor. Você obteria os nomes dos arquivos e seus tamanhos da entrada padrão e poderia ler o conteúdo de cada arquivo comgetline
para impressão. Essa solução também evitaria loops de shell lentos; haveria apenas um únicoawk
.Um possível problema ao listar nomes de arquivos
find
e processá-los com outras ferramentas é que os nomes de arquivos podem conter qualquer caractere, incluindo espaços e novas linhas, exceto caracteres NUL (e/
para nomes base de arquivos).Como você usa o GNU
awk
, que suporta caracteres NUL como separadores de campo, você poderia alimentá-lo com umafind
saída separada por NUL, por exemplo, uma alternância de nomes e tamanhos de arquivo. Isso resolveria todos os possíveis problemas com nomes de arquivo contendo espaços, quebras de linha...Se você realmente quiser um separado
gawk
por arquivo, também pode obter o tamanho dostat
utilitário. Exemplo em quegawk
imprime a primeira linha de cada arquivo, seguida do nome e tamanho. Para melhor legibilidade, colocamos ogawk
script em uma função bash:Variante com
execdir ... {} +
:Usando qualquer awk:
Defina
LC_ALL
como quiser, pois isso não afeta a lógica. Consulte http://awk.freeshell.org/AllAboutGetline para obter mais informações sobre como usargetline
.Acho que o problema é que você está tentando usar
-printf
a saída como parâmetro para o gawk, mas não é assim que funciona. Sua abordagem original não funcionará porque-printf
apenas imprime na saída padrão — não define nenhuma variável que o gawk possa acessar. E$7
em gawk, refere-se ao 7º campo de cada linha de entrada, não às variáveis do shell.Talvez tente isto:
Acredito que esta solução captura os metadados de cada arquivo em uma variável e os passa para o gawk corretamente. Isso
\+
garante que os arquivos sejam processados em lotes para melhor desempenho.Ou uma abordagem alternativa é usar um arquivo de script separado para o gawk ou usar um estilo heredoc;
Espero que isso funcione para você.
Você pode obter informações sobre o arquivo, incluindo seu tamanho, usando
stat
após carregar filefuncs . Por exemploimprimirá o nome do arquivo seguido pelo seu tamanho (em bytes) de todos os arquivos txt no diretório de trabalho atual. Não sei quão rápido ele é comparado a
find
, então teste você mesmo e escreva sobre os resultados.(testado no GNU Awk 5.3.1)