J'ai un dossier avec de nombreux fichiers (xyz1, xyz2, jusqu'à xyz5025) et j'ai besoin d'exécuter un script sur chacun d'eux, obtenant xyz1.faa, xyz2.faa, etc. en tant que sorties.
La commande pour un seul fichier est:
./transeq xyz1 xyz1.faa -table 11
Existe-t-il un moyen de le faire automatiquement? Peut-être un combo à faire?
for file in xyz*; do ./transeq "$file" "${file}.faa" -table 11; done
. Je tape ce genre de chose tout le temps. Et si vous voulez vérifier que les noms de fichiers, etc. sont étendus comme vous le souhaitez, mettez simplement unecho
droit aprèsdo
la première fois, puis revenez dans votre historique de shell et supprimez-le une deuxième fois."$file".faa
est légèrement plus facile à taper dans le cadre d'un one-liner interactif et sûr car.faa
il ne contient aucun métacaractère shell à citer.xyz*
glob récupère également les fichiers .faa. Pour bash, exécutezshopt -s extglob
( référence ), puis utilisezfor file in xyz!(*.faa) ...
pour exclure les fichiers .faa d'être envoyés via la boucle.Si vous installez GNU Parallel, vous pouvez le faire en parallèle comme ceci:
Si votre programme est gourmand en CPU, il devrait accélérer un peu.
la source
Vous pouvez faire quelque chose comme ça sur une
bash
ligne de commande:Nous générons les entiers de 1 à 5025, un / ligne, puis
{}
les alimentons un par un aux xargs, qui encapsule l'entier dans puis le transplante dans la ligne de commande ./transeq de manière appropriée.Si vous ne disposez pas de la fonction d'expansion d'accolade,
{n..m}
vous pouvez invoquer l'seq
utilitaire pour générer ces chiffres.Ou, vous pouvez toujours émuler la génération numérique via:
la source
for i in {1..5025}; do ./transeq "xyz$i" "xyz$i".faa -table 11; done
est beaucoup plus facile à penser et à taper. Si vous souhaitez qu'il imprime des commandes avant de les exécuter, utilisezset -x
.for i in
{1..5025}
pour obtenir exactement le même résultat que le vôtre. Vous pouvez également écrirefor ((i=1 ; i<=5025 ; i++)); do ./transeq "xyz$i" "xyz$i".faa -table 11; done
en bash, mais j'utilise généralement la{a..b}
syntaxe de la plage car elle est plus rapide à taper.Utilisation de find, utile lorsque vos fichiers sont dispersés dans des répertoires
la source
En supposant que vous avez plus d'un cœur et que chaque invocation puisse s'exécuter indépendamment des autres, vous obtiendrez une accélération considérable avec des exécutions parallèles.
Un moyen relativement simple de le faire est via le
-P
paramètre dexargs
- par exemple, si vous avez 4 cœurs:Le
-n 1
ditxargs
de ne choisir qu'un seul argument de la liste pour chaque invocation (par défaut, il passerait beaucoup) , et le-P 4
dit de générer 4 processus en même temps - quand on meurt, un nouveau est généré.À mon humble avis, vous n'avez pas besoin d'installer parallèle GNU pour ce cas simple -
xargs
suffit.la source
Vous pouvez utiliser
xarg
ls | xargs -L 1 -d '\n' your-desired-command
-L 1
fait passer 1 élément à la fois-d '\n'
make output ofls
est divisé en fonction de la nouvelle ligne.la source