Como eu agrego dados de muitos arquivos em um arquivo?

5

Eu tenho essa estrutura de diretórios para cerca de 100 usuários.

users
- user1
  - info.txt
- user2
  - info.txt
- user3
  - info.txt
...

Dentro dos arquivos info.txt , o conteúdo se parece com isso.

5 some_other_info

Basicamente, é apenas uma linha, contendo um número, um espaço e, em seguida, algum texto (pode ter espaços dentro de).

Gostaria de criar um arquivo result.txt semelhante a este.

user1 5
user2 6
user3 7
...

Onde user1 , user2 , user3 , ... corresponde ao nome do diretório e os números correspondem ao que está em seus respectivos arquivos info.txt .

Você pode assumir que os diretórios de usuários não possuem espaços em seus nomes.

O que é uma boa maneira de fazer isso?

    
por Russell 08.10.2013 / 19:06

4 respostas

7
awk '{split(FILENAME,u,"/"); print u[2], $1}' users/*/info.txt
    
por 08.10.2013 / 19:35
6

Você pode fazer isso com um simples loop for .

{
  for userd in users/*/; do 
    if [[ -e "$userd/info.txt" ]]; then
      read num _ < "$userd/info.txt"
      printf '%s %s\n' "$user" "$num"
    fi
  done
} > out.txt
    
por 08.10.2013 / 19:17
3

Uma variação na resposta de Stephane:

$ cd users && \
      find -mindepth 2 -maxdepth 2 -type f -name info.txt  \
    | xargs awk '{ split(FILENAME,u,"/"); print u[2], $1 }'

O uso de (% GNU)find e xargs protege contra o número de usuários excedendo o número máximo de argumentos do programa (que é dependente do sistema).

(xargs irá dividir corretamente a entrada e chamar repetidamente o awk, se necessário)

    
por 08.10.2013 / 20:30
2
for f in users/*/info.txt; do
    set -- $(< $f)
    num=$1

    # choose one of:
    user=$(basename $(dirname $f))
    # or
    dir=${f%/*}; user=${dir##*/}

    echo $user $num
done
    
por 08.10.2013 / 20:00