Ho diversi file (tabelle) denominati come:istituto _
modello _
scenario _
fiume .txt
(istituto , modello , scenario e fiume sono variabili.) Vorrei creare un for
loop che identificherà tutti i file che hanno lo stesso istituto nome e allo stesso tempo lo stesso scenario nome, per aggiungere i risultati di ogni diverso modello nello stesso file di output, utilizzando il seguente comando:
paste filename1.txt filename2.txt > output_file.txt
So come creare un for
scorre su cartelle diverse ma non su nomi di file. Qualcuno ha un'idea?
Come esempio minimo, i nomi dei file potrebbero essere i seguenti:
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
Quindi, vorrei aggiungere i seguenti file insieme:
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
Risposta accettata:
Se i file sono tutti nella stessa directory, puoi:
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
}'
che divide il nome del file su “_” (-F_
), imposta le variabili i,m,s
sulle prime 3 parti del nome del file (istituto,modello,scenario),
e accumula nell'array f il nome del file. L'array è indicizzato
solo dall'istituto e dallo scenario, quindi tutti i modelli sono concatenati
(m non viene utilizzato). L'END finale stampa l'array f e utilizza l'indice (institute_scenario) come nome
per il file di output. Con i tuoi esempi questo produce
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
È quindi necessario eseguire il pipe nella shell per eseguirlo. Aggiungi | sh
all'ultima riga sopra per farlo.
Per rimuovere alcune colonne dai file di input, devi modificare la riga awk
che raccoglie tutti i nomi dei file di input. Nella prima riga awk:
{ i=$1; m=$2; s=$3; f[i"_"s] = f[i"_"s] " " $0 }
il nome del file è "$0". Ad esempio, se modifichi questa riga in:
{ i=$1; m=$2; s=$3; f[i"_"s] = f[i"_"s] sprintf(" <(cut -f4 %s)",$0) }
quindi otterrai l'output di esempio:
paste <(cut -f4 wbm_gfdl_rcp8p5_mississippi.txt) <(cut -f4 wbm_hadgem_rcp8p5_mississippi.txt) >out_wbm_rcp8p5.txt
ma se vuoi tagliare solo il 2° nome del file, è un po' più complicato e
ti serve invece questo:
{ 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 }
così otterrai
paste wbm_gfdl_rcp8p5_mississippi.txt <(cut -f4 wbm_hadgem_rcp8p5_mississippi.txt) >out_wbm_rcp8p5.txt
Se sh
non comprende la sintassi <(cut ...)
quindi sostituiscilo con bash
.