web-dev-qa-db-fra.com

Pour boucle avec noms de fichiers

J'ai plusieurs fichiers (tables) nommés comme: institute_modèle_scénario_- rivière.txt

(institut, modèle, scénario, et rivière sont des variables.) J'aimerais créer un for boucle qui identifiera chaque fichier ayant le même nom institute et en même temps le même scénario nom, afin d’ajouter les résultats de chaque fichier différent model dans le même fichier de sortie, à l'aide de la commande suivante:

paste filename1.txt filename2.txt > output_file.txt

Je sais comment créer une boucle for sur différents dossiers, mais pas sur les noms de fichiers. Quelqu'un a une idée?

Comme exemple minimal, les noms de fichiers pourraient être les suivants:

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

Ensuite, j'aimerais annexer les fichiers suivants:

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
4
steve

Si les fichiers se trouvent tous dans le même répertoire, vous pouvez:

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
         }'

qui divise le nom de fichier en "_" (-F_), définit les variables i, m, s sur les 3 premières parties du nom de fichier (institute, modèle, scénario) et accumule dans le tableau f le nom de fichier. Le tableau est indexé uniquement par l'institut et le scénario, de sorte que tous les modèles sont concaténés (m n'est pas utilisé). La dernière END affiche le tableau f et utilise l'index (institute_scenario) comme nom du fichier de sortie. Avec vos exemples cela produit

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

Vous devez ensuite diriger cela dans le shell pour l'exécuter. Ajoutez | sh à la dernière ligne ci-dessus pour le faire.


Pour supprimer certaines colonnes des fichiers d'entrée, vous devez modifier la ligne awk qui collecte tous les noms de fichiers d'entrée. Dans la 1ère ligne awk:

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

le nom de fichier est le "$ 0". Par exemple, si vous modifiez cette ligne en:

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

alors vous obtiendrez l'exemple de sortie:

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

mais si vous voulez couper uniquement le 2ème nom de fichier, c'est un peu plus compliqué et vous en avez besoin à la place:

{ 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 }

alors vous aurez

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

Si sh ne comprend pas la syntaxe <(cut ...), remplacez-la par bash.

2
meuh

Tout d'abord, il n'y a pas de différence entre une boucle for pour les répertoires et une boucle pour les fichiers. C'est exactement la même chose. Rappelez-vous que sur * nix, tout est un fichier .

Donc, votre boucle ressemblerait à ceci:

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

Si vous ne connaissez pas les noms d'institut et de scénario, vous pouvez simplement l'exécuter pour tous les fichiers et les extraire des noms de fichiers (tant que vos noms ne contiennent pas d'espaces):

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

Peut-être en utilisant la commande ls. Quelque chose comme ls $institute_*_$scenario_*.txt devrait renvoyer tous les fichiers avec le même institut et le même scénario.

1
migrc