Para loop com nomes de arquivos

4

Eu tenho vários arquivos (tabelas) nomeados como: institute _ modelo _ cenário _ rio .txt

( instituto , modelo , cenário , e rio são variáveis.) Eu gostaria de criar um for loop que identificará cada arquivo que tiver o mesmo nome institute e ao mesmo tempo o mesmo nome cenário , para acrescentar os resultados de cada diferente > model no mesmo arquivo de saída, usando o seguinte comando:

paste filename1.txt filename2.txt > output_file.txt

Eu sei como criar um loop for sobre pastas diferentes, mas não sobre nomes de arquivos. Alguém tem uma ideia?

Como exemplo mínimo, os nomes dos arquivos podem ser os seguintes:

wbm_gfdl_rcp8p5_mississippi.txt
wbm_hadgem_rcp8p5_mississippi.txt
matsiro_gfdl_rcp8p5_mississippi.txt
matsiro_ipsl_rcp4p5_mississippi.txt
matsiro_hadgem_rcp4p5_mississippi.txt
matsiro_miroc_rcp8p5_mississippi.txt

Depois, gostaria de anexar os seguintes arquivos juntos:

wbm_gfdl_rcp8p5_mississippi.txt with
wbm_hadgem_rcp8p5_mississippi.txt

matsiro_ipsl_rcp4p5_mississippi.txt with
matsiro_hadgem_rcp4p5_mississippi.txt

matsiro_gfdl_rcp8p5_mississippi.txt with
matsiro_miroc_rcp8p5_mississippi.txt
    
por steve 07.10.2015 / 13:56

3 respostas

2

Se os arquivos estiverem todos no mesmo diretório, você pode:

ls |
awk -F_ '{ i=$1; m=$2; s=$3; f[i"_"s] = f[i"_"s] " " $0 }
         END{ for(insc in f)
                printf "paste%s >out_%s.txt\n",f[insc],insc
         }'

que divide o nome do arquivo em "_" ( -F_ ), define as variáveis i, m, s para as 3 primeiras partes do nome do arquivo (instituto, modelo, cenário), e se acumula na matriz f do nome do arquivo. A matriz é indexada somente pelo instituto e cenário, então todos os modelos são concatenados (não é usado). A END final imprime a matriz f e usa o índice (institute_scenario) como nome para o arquivo de saída. Com seus exemplos, isso produz

paste wbm_gfdl_rcp8p5_mississippi.txt wbm_hadgem_rcp8p5_mississippi.txt >out_wbm_rcp8p5.txt
paste matsiro_hadgem_rcp4p5_mississippi.txt matsiro_ipsl_rcp4p5_mississippi.txt >out_matsiro_rcp4p5.txt
paste matsiro_gfdl_rcp8p5_mississippi.txt matsiro_miroc_rcp8p5_mississippi.txt >out_matsiro_rcp8p5.txt

Você então precisa canalizar isso no shell para executá-lo. Adicione | sh à última linha acima para fazer isso.

Para remover algumas colunas dos arquivos de entrada, você precisa alterar a linha do awk que está coletando todos os nomes de arquivos de entrada. Na primeira linha do awk:

{ i=$1; m=$2; s=$3; f[i"_"s] = f[i"_"s] " " $0 }

o nome do arquivo é o "$ 0". Por exemplo, se você alterar esta linha para:

{ i=$1; m=$2; s=$3; f[i"_"s] = f[i"_"s] sprintf(" <(cut -f4 %s)",$0) }

então você receberá a saída de exemplo:

paste <(cut -f4 wbm_gfdl_rcp8p5_mississippi.txt) <(cut -f4 wbm_hadgem_rcp8p5_mississippi.txt) >out_wbm_rcp8p5.txt

mas se você quiser cortar apenas o segundo nome de arquivo, é um pouco mais complicado e você precisa disso:

{ i=$1; m=$2; s=$3; 
  if(f[i"_"s]=="")add = $0; else add = sprintf("<(cut -f4 %s)",$0);
  f[i"_"s] = f[i"_"s] " " add }

para que você receba

paste wbm_gfdl_rcp8p5_mississippi.txt <(cut -f4 wbm_hadgem_rcp8p5_mississippi.txt) >out_wbm_rcp8p5.txt

Se sh não entender a sintaxe <(cut ...) , substitua-a por bash .

    
por meuh 07.10.2015 / 14:28
6

Em primeiro lugar, não há diferença entre um loop for para diretórios e outro para arquivos. É exatamente a mesma coisa. Lembre-se que no * nix, tudo é um arquivo .

Então, o seu loop seria algo assim:

for institute in institute1 institute2 institute3
do
    for scenario in scenario1 scenario2 scenario3
    do
        paste "$institute"_*_"$scenario"* > "$institute"_"$scenario".out
    done
done

Se você não conhece os nomes do instituto e do cenário, pode executar isso para todos os arquivos e extraí-los dos nomes de arquivos (contanto que seus nomes não contenham espaços em branco):

for f in *; do echo "${f/_*} ${f##*_}"; done | 
    sort -u | while read ins sce; do 
        paste "$ins"_*_"$sce"* > "$ins"_"$sce".out
    done
    
por terdon 07.10.2015 / 15:11
1

Talvez usando o comando ls. Algo como ls $institute_*_$scenario_*.txt deve retornar todos os arquivos com o mesmo instituto e cenário.

    
por migrc 07.10.2015 / 14:14