J'ai besoin de traiter un groupe de fichiers dans un répertoire en les passant dans un matlab ou un script python.

Pour chaque fichier d'entrée FileName.IN dans le répertoire, j'ai besoin d'un fichier de sortie FileName.OUT.

Peu importe si la solution est un Python ou un script bash.

Pour atteindre mon objectif, j'essaye GNU Make (ou Python Snakemake), mais je suis un peu coincé dessus. Il semble que je puisse dire que GNU Make doit faire: "Hé, pour chaque fichier de sortie (cible) FileName.out recherchez le FileName.IN correspondant (prérequis)" .

Cependant, ce que je veux faire est exactement le contraire, comme indiqué précédemment.

  • make (ou snakemake) est-il le bon choix?
  • Que suggéreriez-vous d'autre?

Mon code makefile ressemble à ceci mais il ne fait pas le travail (je suis un débutant avec GNU make):

in_files = *.IN
out_files = *.out
$(out_files) : $(in_files)
    matlab -nosplash -nodesktop -r "a_matlab_function('$<','$@')"
3
Robyc 17 janv. 2017 à 16:55

2 réponses

Meilleure réponse

Je ne sais rien de Snakemake, mais dans GNU Make, vous pouvez transformer in_files pour donner le out_files:

in_files = $(wildcard *.IN)
out_files = $(in_files:.IN=.out)

Ensuite, vous créez une cible factice qui dépend de toutes les sorties:

all: $(out_files)
.PHONY: all

Et enfin une règle pour créer une sortie à partir d'une entrée:

%.out: %.IN
    matlab -nosplash -nodesktop -r "a_matlab_function('$<','$@')"
5
Toby Speight 17 janv. 2017 à 14:15

Je pense que vous voulez juste une boucle for bash:

for f in *.IN; do
   out=${f%IN}OUT                # Work out name of output file
   echo IN:"$f"                  # Show input file to user
   echo OUT:"$out"               # Show output file to user
   matlab <options> "$f" "$out"  # Run Matlab
done

Donc, si j'ai ces fichiers:

ls *IN

aThird.IN   
another one.IN
b.IN

J'obtiendrai ceci:

IN:aThird.IN
OUT:aThird.OUT
IN:another one.IN
OUT:another one.OUT
IN:b.IN
OUT:b.OUT

Ou, en une ligne:

for f in *.IN; do out=${f%IN}OUT; matlab ... "$f" ... "$out"; done

Notes :

Bien que votre question suggère d'utiliser make , rien n'indique avec certitude si vous prévoyez toujours d'exécuter toutes les tâches, ou si parfois certaines tâches n'ont pas besoin d'être exécutées - probablement parce que les fichiers de sortie existent déjà et que ce n'est pas nécessaire pour les exécuter. Si vous ne voulez pas que toutes les tâches soient exécutées à chaque fois, vous serez probablement mieux avec make .

De plus, si Matlab peut exécuter des instances parallèles, la syntaxe GNU Parallel est intéressante pour des choses comme celle-ci:

parallel --dry-run matlab {} {.}.OUT ::: *IN

Sortie

matlab another\ one.IN another\ one.OUT
matlab aThird.IN aThird.OUT
matlab b.IN b.OUT 

Ici, le --dry-run vous montre les commandes qui seraient exécutées, bien qu'il n'exécute actuellement rien.

2
Mark Setchell 17 janv. 2017 à 14:45