usando o awk com find -exec

2

Eu tenho uma estrutura de diretórios com 14 diretórios contendo um monte de arquivos contendo dados em um formato de três colunas (separados por abas). Eu pretendia usar find e awk para extrair a segunda coluna de cada um desses arquivos e enviá-la com o mesmo nome de arquivo, mas sob uma pasta raiz diferente. Aqui o esboço do meu diretório.

dados / todos - > AA, AB, AC, AD ... (A * sendo pastas contendo os arquivos com dados armazenados em um formato de 3 colunas, por exemplo, AA100.txt, AA101.txt ...)

Eu quero ter os arquivos modificados (uma coluna) com o mesmo nome, mas todos sob um novo diretório raiz de dados / pos (em oposição a dados / all /) - > AA, AB, AC, AD ... (novamente, cada um contendo A * 100.txt, A * 101 ...)

Minha tentativa foi usar find -exec e dar a ele o comando awk, mas estou tendo problemas com a saída do arquivo para o lugar certo.

ao estar em data / all /

find * -type f -exec awk '{print$2}' '{}' > ../pos/'{}' \;

No entanto {} como curinga para o arquivo de entrada não parece funcionar ao produzir o arquivo?

O que estou fazendo de errado? (Eu estou em um servidor ubuntu btw)

    
por conipo 18.12.2013 / 14:44

2 respostas

3

Você poderia tentar sem encontrar, se tudo o que você quer é todos os arquivos. Enquanto em data/all/ , execute isto:

for file in ./*; do awk '{print$2}' "$file" > "../pos/$(basename $file)"; done

Se você quiser cobrir os arquivos em toda a hierarquia em /data/all , é possível ativar a opção globstar se estiver usando o bash (acredito que isso "funcione" apenas no zsh) e use ** para corresponder a todos os arquivos:

shopt -s globstar
for file in ./**; do awk '{print$2}' "$file" > "../pos/$(basename $file)"; done
    
por 18.12.2013 / 14:50
2

What am I doing wrong?

Você está usando o redirecionamento > ../pos/'{}' como se fosse manipulado por find ou awk , mas os redirecionamentos são manipulados pelo shell. No seu caso, significa que você pode redirecionar apenas a saída de todo o find (não a saída de awk ).

Observe que você geralmente não precisa usar curinga como * para o caminho inicial de find . É o caminho comum find . o que você queria fazer ou há algum motivo para find * ?

Soluções

Aqui vamos manter a flexibilidade de find em contraste com a solução de Jacobo de Vera. Execute awk em um loop de shell:

find . -type f -print0 |
  while read -r -d $'
find . -type f -exec sh -c 'awk "{print \}" "{}" > "../pos/{}"' \;
' x; do awk '{print $2}' "$x" > "../pos/$(basename "$x")" done

A forma original com -exec será menos eficiente porque, para cada arquivo, será lançado um shell, além de awk , e o escape em vários níveis será bastante complicado aqui:

find . -type f -print0 |
  while read -r -d $'
find . -type f -exec sh -c 'awk "{print \}" "{}" > "../pos/{}"' \;
' x; do awk '{print $2}' "$x" > "../pos/$(basename "$x")" done

Também pode haver uma solução alternativa para fazer o redirecionamento em awk .

    
por 18.12.2013 / 16:02

Tags