Aller au contenu
Administration Linux medium

GNU Parallel : exécuter en parallèle

26 min de lecture

Quand vous devez traiter des centaines de fichiers, convertir des images en masse ou exécuter des scripts sur plusieurs serveurs, lancer les tâches une par une est trop lent. GNU Parallel permet d'exécuter plusieurs commandes simultanément, en exploitant tous les cœurs de votre CPU. Là où xargs traite séquentiellement, parallel répartit la charge et accélère drastiquement vos traitements batch.

  • Exécuter des commandes en parallèle avec :::
  • Contrôler le nombre de jobs avec -j
  • Utiliser les placeholders ({}, {.}, {/})
  • Gérer les fichiers avec espaces et caractères spéciaux
  • Surveiller la progression et gérer les erreurs
  • Combiner parallel avec find et d'autres commandes

GNU Parallel est l'évolution logique de xargs pour les traitements en masse. Voici comment il se positionne :

CommandeSpécialitéQuand l'utiliser
parallelExécution parallèleTraitement en masse, performance maximale
xargsExécution séquentielleCommandes simples, une par une
make -jBuild parallèleCompilation de projets
& / waitJobs backgroundQuelques tâches indépendantes

Avantages de parallel sur xargs :

  • Exécution réellement parallèle (pas juste -P)
  • Barre de progression (--bar, --eta)
  • Gestion des erreurs avancée (--halt)
  • Placeholders riches ({.}, {/}, {#}...)
  • Exécution sur serveurs distants (-S)

🧠 Modèle mental — Comment fonctionne parallel

parallel = Pour chaque argument → Lancer N commandes simultanément → Collecter les résultats

Modèle mental parallel : Liste arguments (stdin, :::, ::::) → Commande (cmd {}) → N jobs en parallèle → Sorties collectées + Options (-j, --bar)

Points clés

  • parallel lit les arguments et lance plusieurs instances de la commande simultanément
  • Par défaut, parallel lance autant de jobs que de cœurs CPU
  • {} représente l'argument courant, {.} sans extension, {/} nom de base
  • ::: passe des arguments inline, :::: lit depuis un fichier
  • L'ordre des sorties n'est PAS garanti (exécution parallèle)

Règles d'or

1
Toujours tester avec --dry-run d'abord Vérifie les commandes qui seront exécutées sans les lancer.
2
Limiter les jobs avec -j pour éviter la surcharge Trop de jobs parallèles peut saturer CPU, mémoire ou disque.

Vocabulaire essentiel

:::
Passe des arguments directement en ligne de commande
::::
Lit les arguments depuis un fichier
{}
Placeholder pour l'argument courant
-j N
Nombre de jobs en parallèle (défaut: nb CPU)
--dry-run
Affiche les commandes sans les exécuter
--bar
Affiche une barre de progression
📚 Pour aller plus loin — 12 options avancées
{.}
Argument sans extension
{/}
Nom de base (sans chemin)
{//}
Chemin du répertoire
{/.}
Nom de base sans extension
{#}
Numéro du job (séquence)
{%}
Numéro du slot (worker)
--colsep
Séparateur de colonnes pour plusieurs champs
--halt
Comportement sur erreur (now,fail=1...)
--results
Enregistre stdout/stderr dans un dossier
--eta
Affiche le temps restant estimé
--null
Arguments séparés par NUL (pour find -print0)
-S
Exécution sur serveurs distants (SSH)

Contrairement à xargs qui passe les arguments à une seule instance de commande, parallel lance N instances simultanées (N = nombre de cœurs CPU par défaut).

Fenêtre de terminal
parallel [options] commande ::: arguments # Arguments inline
parallel [options] commande :::: fichier.txt # Arguments depuis fichier
cat liste.txt | parallel [options] commande {} # Arguments depuis stdin

Options principales :

OptionDescriptionExemple
-j NN jobs en parallèle (défaut: nb CPU)parallel -j 4 ...
--dry-runAffiche sans exécuterparallel --dry-run rm ...
--barBarre de progressionparallel --bar cmd ...
--haltComportement sur erreur--halt now,fail=1
-kPréserve l'ordre des sortiesparallel -k echo ...
PartieQuestionExemplesObligatoire ?
SourceD'où viennent les arguments ?:::, ::::, stdin✅ Oui
CommandeQuelle commande exécuter ?gzip {}, convert✅ Oui
ContrôleCombien de parallélisme ?-j 4, --bar❌ Non (défauts)
PlaceholderSignificationExemple (/path/photo.jpg)
{}Argument complet/path/photo.jpg
{.}Sans extension/path/photo
{/}Nom de base (sans chemin)photo.jpg
{//}Chemin du répertoire/path
{/.}Nom de base sans extensionphoto
{#}Numéro du job (1, 2, 3...)1
{%}Numéro du slot (worker)2

Exemple de conversion :

Fenêtre de terminal
# Convertir photo.jpg → photo.png
parallel convert {} {.}.png ::: *.jpg
# Résultat pour photo.jpg :
# convert photo.jpg photo.png
SourceSyntaxeExemple
Inline::: arg1 arg2parallel echo ::: a b c
Fichier:::: fichier.txtparallel wget :::: urls.txt
Stdincmd | parallelfind . | parallel gzip
Multi-colonnes--colsepparallel --colsep ',' cp {1} {2}
Fenêtre de terminal
# Défaut : autant de jobs que de cœurs CPU
parallel gzip ::: *.log
# Limiter à 4 jobs simultanés
parallel -j 4 gzip ::: *.log
# Un seul job (séquentiel, pour debug)
parallel -j 1 gzip ::: *.log
# Autant de jobs que d'arguments (attention !)
parallel -j 0 gzip ::: *.log

⚠️ Attention : trop de jobs parallèles peut saturer le système (CPU, mémoire, I/O disque). Commencez par -j 4 et ajustez.

Le piège classique : les fichiers avec espaces sont mal découpés.

Fenêtre de terminal
# ❌ DANGER : "mon fichier.jpg" devient "mon" et "fichier.jpg"
ls *.jpg | parallel echo {}
# ✅ CORRECT : utiliser find -print0 + --null
find . -name "*.jpg" -print0 | parallel --null echo {}

La combinaison find -print0 | parallel --null est le pattern sécurisé pour tous les traitements de fichiers.

ErreurCauseSolution
Fichiers mal découpésEspaces dans les nomsfind -print0 | parallel --null
Sorties mélangéesExécution parallèleAjouter -k ou --line-buffer
Système saturéTrop de jobsLimiter avec -j 4
Fichiers supprimés par erreurPas de testTOUJOURS --dry-run d'abord
SSH demande mot de passeClé non configuréessh-copy-id user@serveur

GNU Parallel n'est pas toujours installé par défaut :

Fenêtre de terminal
# Debian/Ubuntu
sudo apt install parallel
# CentOS/RHEL/Fedora
sudo dnf install parallel
# macOS (Homebrew)
brew install parallel
# Vérification
parallel --version

Maintenant que vous comprenez la logique de parallel, voici dix modèles prêts à l'emploi. Chacun donne sa formule générale et un exemple concret.

Lancer la même commande sur plusieurs arguments.

Fenêtre de terminal
parallel commande ::: arg1 arg2 arg3 # formule
parallel gzip ::: *.log # exemple
  • ::: : sépare la commande de la liste d'arguments

Lire les arguments depuis un pipe.

Fenêtre de terminal
cat liste.txt | parallel commande {} # formule
find . -name "*.jpg" | parallel convert {} {.}.png # exemple
  • {} : placeholder de l'argument courant

Contrôler le nombre de jobs simultanés.

Fenêtre de terminal
parallel -j N commande ::: arguments # formule
parallel -j 4 gzip ::: *.log # exemple
  • -j N : N jobs maximum (défaut : nombre de cœurs CPU)
  • -j 0 : autant de jobs que d'arguments

Vérifier les commandes avant de les exécuter.

Fenêtre de terminal
parallel --dry-run commande ::: arguments # formule
parallel --dry-run rm ::: *.bak # exemple
  • --dry-run : affiche les commandes sans rien lancer — indispensable avant rm

Convertir des fichiers en changeant leur extension.

Fenêtre de terminal
parallel commande {} {.}.new_ext ::: fichiers # formule
parallel ffmpeg -i {} {.}.mp3 ::: *.wav # exemple
  • {.} : argument sans extension — {/} : nom de base — {//} : répertoire

Traiter sans risque les noms contenant des espaces.

Fenêtre de terminal
find . -print0 | parallel --null commande {} # formule
find . -name "*.jpg" -print0 | parallel --null convert {} {.}.png # exemple
  • -print0 + --null : séparateur nul — le couple sûr pour les fichiers

Afficher l'avancement des tâches.

Fenêtre de terminal
parallel --bar commande ::: arguments # formule
parallel --bar --eta gzip ::: *.log # exemple
  • --bar : barre de progression — --eta : temps restant estimé

Contrôler le comportement quand une tâche échoue.

Fenêtre de terminal
parallel --halt now,fail=1 commande ::: arguments # formule
parallel --halt now,fail=1 ./script.sh ::: *.txt # exemple
  • now,fail=1 : stoppe dès la première erreur
  • soon,fail=20% : stoppe au-delà de 20 % d'échecs

Utiliser plusieurs champs par ligne d'un fichier.

Fenêtre de terminal
parallel --colsep ',' commande {1} {2} :::: fichier.csv # formule
parallel --colsep ',' cp {1} {2} :::: batch.csv # exemple
  • --colsep : séparateur de colonnes — {1}, {2} : les colonnes
  • :::: : lit les arguments depuis un fichier

Distribuer les tâches sur plusieurs machines via SSH.

Fenêtre de terminal
parallel -S serveur1,serveur2 commande ::: arguments # formule
parallel -S srv1,srv2,srv3 hostname ::: {1..10} # exemple
  • -S : liste des serveurs SSH (clé SSH sans mot de passe requise)

Huit erreurs reviennent constamment avec parallel. Certaines sont destructrices, d'autres saturent simplement la machine.

Fenêtre de terminal
parallel rm ::: *.bak # ❌ supprime immédiatement, sans retour possible

Symptôme : des fichiers supprimés par erreur. Cause : aucune vérification des commandes avant exécution.

Fenêtre de terminal
parallel --dry-run rm ::: *.bak # ✅ prévisualiser, puis relancer sans --dry-run
Fenêtre de terminal
parallel -j 100 gzip ::: *.log # ❌ trop de jobs : système saturé

Symptôme : système lent, mémoire saturée, swap intense. Cause : trop de processus parallèles pour les ressources disponibles.

Fenêtre de terminal
parallel -j 4 gzip ::: *.log # ✅ limiter à un nombre raisonnable
Fenêtre de terminal
ls *.jpg | parallel echo {} # ❌ casse sur "mon fichier.jpg"

Symptôme : les arguments sont coupés au niveau des espaces. Cause : le retour à la ligne est le séparateur par défaut.

Fenêtre de terminal
find . -name "*.jpg" -print0 | parallel --null echo {} # ✅ séparateur nul
Fenêtre de terminal
parallel echo ::: 1 2 3 4 5 # ❌ affichage dans un ordre aléatoire

Symptôme : résultats désordonnés. Cause : l'exécution parallèle ne garantit aucun ordre.

Fenêtre de terminal
parallel -k echo ::: 1 2 3 4 5 # ✅ -k préserve l'ordre des sorties
Fenêtre de terminal
parallel commande ::: args # ❌ les lignes de plusieurs jobs se mélangent

Symptôme : lignes de sortie entrelacées, illisibles. Cause : aucune synchronisation de la sortie entre jobs.

Fenêtre de terminal
parallel --line-buffer commande ::: args # ✅ --line-buffer (ou --group)
Fenêtre de terminal
parallel -S serveur commande ::: args # ❌ bloque sur la demande de mot de passe

Symptôme : exécution figée, timeout. Cause : authentification SSH par clé non configurée.

Fenêtre de terminal
ssh-copy-id user@serveur # ✅ configurer la clé, puis relancer parallel
Fenêtre de terminal
parallel echo "File: {}" ::: *.txt # ❌ le shell interprète les guillemets

Symptôme : arguments mal passés, caractères spéciaux interprétés. Cause : le shell traite les guillemets avant parallel.

Fenêtre de terminal
parallel echo 'File: {}' ::: *.txt # ✅ guillemets simples
Fenêtre de terminal
parallel "cat {} >> output.txt" ::: *.log # ❌ fichier de sortie corrompu

Symptôme : sortie corrompue, lignes mélangées. Cause : plusieurs processus écrivent dans le même fichier en même temps.

Fenêtre de terminal
parallel "cat {} > {}.out" ::: *.log && cat *.out > output.txt # ✅ un fichier par job, puis fusion

Rien ne remplace la pratique. Créez l'environnement de test ci-dessous, puis déroulez les huit étapes. À la fin, nettoyez avec rm -rf ~/parallel-lab.

Ce script crée une arborescence dans ~/parallel-lab : des images (dont certaines avec des espaces dans le nom), des logs, une liste de serveurs, une liste d'URLs et un CSV.

Fenêtre de terminal
# Créer le lab
mkdir -p ~/parallel-lab/{images,logs,data}
cd ~/parallel-lab
# Fichiers images simulés
for i in {1..10}; do
echo "image $i data" > images/photo_$i.jpg
done
# Fichiers avec espaces dans le nom
echo "data 1" > "images/mon fichier 1.jpg"
echo "data 2" > "images/photo vacances 2024.jpg"
# Fichiers de logs
for i in {1..5}; do
echo "Log content $i" > logs/app_$i.log
done
# Liste d'URLs
cat > urls.txt << 'EOF'
https://example.com/file1.txt
https://example.com/file2.txt
https://example.com/file3.txt
EOF
# Fichier CSV pour les tests multi-colonnes
cat > data/batch.csv << 'EOF'
fichier1,output1
fichier2,output2
fichier3,output3
EOF
echo "✅ Lab créé dans ~/parallel-lab"
ls -la ~/parallel-lab/
  1. Première commande parallèle. Exécutez echo sur plusieurs arguments avec :::.

    Fenêtre de terminal
    parallel echo ::: un deux trois quatre

    ::: passe les arguments à parallel ; chaque echo s'exécute en parallèle (l'ordre varie).

  2. Utiliser le placeholder {}. Affichez « Traitement de … » pour chaque image.

    Fenêtre de terminal
    ls ~/parallel-lab/images/*.jpg | parallel echo "Traitement de {}"

    {} est remplacé par chaque ligne de l'entrée standard.

  3. Tester sans exécuter. Vérifiez les suppressions qui seraient effectuées, sans rien supprimer.

    Fenêtre de terminal
    ls ~/parallel-lab/logs/*.log | parallel --dry-run rm {}

    --dry-run affiche les commandes sans les lancer — essentiel avant un rm.

  4. Limiter le parallélisme. Lancez 6 sleep de 1 seconde, 2 à la fois.

    Fenêtre de terminal
    parallel -j 2 sleep 1 ::: {1..6}

    -j 2 limite à 2 jobs simultanés — l'ensemble prend environ 3 secondes.

  5. Transformer des fichiers. Simulez la conversion des .jpg en .png.

    Fenêtre de terminal
    ls ~/parallel-lab/images/*.jpg | parallel --dry-run echo convert {} {.}.png

    {.} retire l'extension — idéal pour les conversions de format.

  6. Gérer les fichiers avec espaces. Traitez les images, espaces compris.

    Fenêtre de terminal
    find ~/parallel-lab/images -name "*.jpg" -print0 | parallel --null echo "Fichier : {}"

    -print0 et --null préservent les noms contenant des espaces.

  7. Afficher la progression. Lancez des tâches avec une barre de progression.

    Fenêtre de terminal
    parallel --bar sleep 0.5 ::: {1..10}

    --bar affiche la progression ; --eta ajoute le temps restant estimé.

  8. Arrêt sur erreur. Faites stopper parallel dès la première erreur.

    Fenêtre de terminal
    parallel --halt now,fail=1 'test {} = 3 && exit 1; echo {}' ::: {1..5}

    --halt now,fail=1 arrête tout dès qu'un job renvoie un code d'erreur.

Huit exercices pour valider votre maîtrise. Ils se traitent sur le lab ~/parallel-lab. Cherchez d'abord par vous-même, puis dépliez la solution pour vous corriger.

Exercice 1 — Premiers pas avec :::. Affichez les nombres de 1 à 5 en parallèle. Indice : ::: passe les arguments à parallel.

Voir la solution
Fenêtre de terminal
parallel echo ::: 1 2 3 4 5

::: sépare la commande des arguments ; chaque nombre est passé à echo.

Exercice 2 — Compression parallèle. Compressez tous les fichiers .log du lab avec gzip. Indice : ::: avec le glob *.log.

Voir la solution
Fenêtre de terminal
parallel gzip ::: ~/parallel-lab/logs/*.log

Chaque fichier .log est compressé simultanément.

Exercice 3 — Mode simulation. Vérifiez les commandes qui supprimeraient les fichiers .bak, sans rien supprimer. Indice : --dry-run.

Voir la solution
Fenêtre de terminal
parallel --dry-run rm ::: *.bak

--dry-run est indispensable avant toute commande destructive.

Exercice 4 — Limiter le parallélisme. Lancez 6 sleep de 1 seconde, mais 2 à la fois seulement. Indice : -j limite le nombre de jobs.

Voir la solution
Fenêtre de terminal
time parallel -j 2 sleep 1 ::: {1..6}

-j 2 limite à 2 jobs simultanés : 6 jobs = 3 vagues de 2, soit ≈ 3 secondes.

Exercice 5 — Conversion de fichiers. Simulez (avec echo) la conversion des images .jpg en .png. Indice : {.} donne le nom sans extension.

Voir la solution
Fenêtre de terminal
ls ~/parallel-lab/images/*.jpg | parallel --dry-run convert {} {.}.png

{.} retire l'extension — parfait pour les conversions de format.

Exercice 6 — Fichiers avec espaces. Listez tous les .jpg du lab de façon sûre, y compris ceux avec des espaces. Indice : find -print0 + parallel --null.

Voir la solution
Fenêtre de terminal
find ~/parallel-lab/images -name "*.jpg" -print0 | parallel --null echo "Fichier : {}"

-print0 et --null gèrent les espaces et caractères spéciaux.

Exercice 7 — Multi-colonnes CSV. À partir de batch.csv, simulez des copies source → destination. Indice : --colsep et {1}, {2}.

Voir la solution
Fenêtre de terminal
parallel --colsep ',' --dry-run cp {1} {2} :::: ~/parallel-lab/data/batch.csv

--colsep définit le séparateur ; {1} et {2} référencent les colonnes.

Exercice 8 — Gestion des erreurs. Lancez des commandes avec arrêt à la première erreur. Indice : --halt now,fail=1.

Voir la solution
Fenêtre de terminal
parallel --halt now,fail=1 'if [ {} = 3 ]; then exit 1; fi; echo {}' ::: {1..5}

--halt now,fail=1 arrête tout dès qu'un job renvoie un code d'erreur.

Quand parallel se comporte mal, isolez la cause avec ces quatre vérifications avant tout.

Fenêtre de terminal
# Voir les commandes sans les exécuter
parallel --dry-run commande ::: arguments
# Afficher chaque commande avant exécution
parallel --verbose commande ::: arguments
# Remplacer la commande par echo pour observer
parallel echo "Je ferais : cmd {}" ::: args
# Exécuter séquentiellement pour isoler un problème
parallel -j 1 commande ::: arguments
Message d'erreurCause probableSolution
Warning: Input is read from the terminalAucune entrée (ni ::: ni pipe)Ajouter ::: avec des arguments, ou un pipe
command not foundCommande absente du PATHVérifier avec which, ou utiliser un chemin absolu
Permission deniedScript non exécutable, droits insuffisantschmod +x sur le script, vérifier les droits
ssh: Connection timed outServeur injoignable ou pare-feuTester ssh serveur echo OK, vérifier le réseau
FormeRôleExemple
parallel commande ::: arg1 arg2Arguments en ligne de commandeparallel gzip ::: *.log
cat liste | parallel commande {}Arguments depuis stdinfind . | parallel echo {}
parallel commande :::: fichier.txtArguments depuis un fichierparallel wget :::: urls.txt
parallel --colsep "," cmd {1} {2} :::: data.csvArguments multi-colonnesparallel --colsep "," cp {1} {2} :::: batch.csv
OptionRôleExemple
-j NN jobs en parallèle (défaut : nb CPU)parallel -j 4 gzip ::: *.log
--dry-runAffiche sans exécuterparallel --dry-run rm ::: *.bak
--verboseAffiche chaque commandeparallel --verbose cmd ::: args
-k (--keep-order)Préserve l'ordre des sortiesparallel -k echo ::: 1 2 3
--barBarre de progressionparallel --bar cmd ::: {1..100}
--etaTemps restant estiméparallel --eta cmd ::: args
--halt now,fail=1Stoppe à la première erreurparallel --halt now,fail=1 cmd ::: args
--nullEntrées séparées par un caractère nulfind -print0 | parallel --null cmd
PlaceholderRôleExemple
{}Argument completecho {}
{.}Sans extensionconvert {} {.}.png
{/}Nom de base (sans chemin)echo {/}
{//}Chemin du répertoiremkdir -p {//}/out
{/.}Nom de base sans extensionecho {/.}
{#}Numéro du jobecho "Job {#} : {}"
{1}, {2}Colonnes (avec --colsep)cp {1} {2}

Vous maîtrisez parallel lorsque vous pouvez cocher chacun de ces points :

  • Je sais utiliser ::: pour passer des arguments
  • Je sais tester avec --dry-run avant d'exécuter
  • Je sais limiter les jobs avec -j
  • Je sais utiliser {} et {.} pour les placeholders
  • Je sais gérer les fichiers avec espaces grâce à --null
  • Je sais traiter un fichier CSV multi-colonnes avec --colsep
  • Je sais gérer les erreurs avec --halt
  • Je sais afficher la progression avec --bar et --eta
Fenêtre de terminal
# Convertir toutes les images en parallèle
find . -name "*.jpg" -print0 | parallel --null --bar convert {} {.}.png
# Compresser des vidéos (limiter à 2 jobs car gourmand)
parallel -j 2 --eta ffmpeg -i {} -c:v libx264 {.}.mp4 ::: *.avi
Fenêtre de terminal
# Télécharger une liste d'URLs
parallel --bar wget :::: urls.txt
# Avec limite de bande passante par job
parallel -j 4 wget --limit-rate=1M {} :::: urls.txt
Fenêtre de terminal
# Lancer une commande sur plusieurs serveurs
parallel -S srv1,srv2,srv3 hostname
# Copier un fichier vers tous les serveurs
parallel -S srv1,srv2,srv3 --transferfile {} echo "Copié: {}" ::: config.yml

Prérequis : SSH sans mot de passe configuré (ssh-copy-id).

Fenêtre de terminal
# Fichier batch.csv : source,destination
# fichier1.txt,/backup/fichier1.txt
# fichier2.txt,/backup/fichier2.txt
parallel --colsep ',' cp {1} {2} :::: batch.csv
Critèreparallelxargs
Parallélisme natif✅ Optimisé⚠️ Limité (-P)
Barre de progression✅ --bar, --eta❌ Non
Gestion des erreurs✅ --halt❌ Basique
Placeholders{}, {.}, {/}, {#}⚠️ {} seulement
Serveurs distants✅ -S❌ Non
Disponibilité⚠️ À installer✅ Préinstallé
Complexité⚠️ Plus d'options✅ Plus simple

En résumé :

  • xargs pour les cas simples où la commande est préinstallée
  • parallel dès que vous avez besoin de performance, progression ou robustesse
  1. ::: passe des arguments inline, :::: lit depuis un fichier
  2. {} = argument complet, {.} = sans extension, {/} = nom de base
  3. -j N limite le parallélisme — ne pas saturer le système
  4. --dry-run est OBLIGATOIRE avant toute commande destructive (rm, mv)
  5. find -print0 | parallel --null = pattern sécurisé pour les fichiers
  6. --bar et --eta pour surveiller la progression
  7. --halt now,fail=1 pour stopper à la première erreur
  8. -k préserve l'ordre des sorties si important

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracing. Aujourd'hui, ce site ne couvre même pas mes frais d'hébergement, d'électricité, de matériel, de logiciels, mais surtout de cafés.

Un soutien régulier, même symbolique, m'aide à garder ces ressources gratuites et à continuer de produire des guides de qualité. Merci pour votre appui.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn