Linux / Commande printenv : lire les variables d’environnement

printenv NOM affiche la valeur d’une variable reçue dans l’environnement du programme, sans la modifier. Pour distinguer une valeur vide d’une variable absente, vérifiez son statut de retour : avec GNU printenv, 0 indique que les noms demandés ont été trouvés et 1 qu’au moins un manque.

Consulter un nom précis au lieu de tout l’environnement

printenv lit l’environnement qui lui est transmis au lancement. Il ne lit pas toutes les variables internes du shell parent et ne change aucune valeur. Sa syntaxe générale est :

printenv [options] [NOM ...]

Pour un essai indépendant de vos réglages, transmettez une variable de démonstration avec env :

env DEMO_MODE=essai printenv DEMO_MODE

La réponse attendue est essai, sans préfixe DEMO_MODE=. Le guide de env explique comment transmettre cette valeur pour un seul lancement sans changer le parent.

Avec un nom tel que PATH, passez le nom lui-même :

printenv PATH

printenv "$PATH" aurait un autre sens : le shell remplacerait d’abord $PATH par son contenu, puis printenv chercherait une variable portant ce contenu comme nom.

Sans nom, printenv affiche l’ensemble des variables, avec leurs noms et valeurs. Cette sortie peut contenir des identifiants d’accès ou des jetons ; privilégiez les noms utiles plutôt qu’un affichage global destiné à être partagé. Vérifiez aussi l’implémentation si une option ne fonctionne pas :

type -a printenv
printenv --version
printenv --help

Comprendre les valeurs multiples, vides et absentes

Une sortie partielle peut accompagner un échec

env DEMO_MODE=essai DEMO_LEVEL=2 printenv DEMO_MODE DEMO_LEVEL

Les valeurs essai et 2 apparaissent dans l’ordre des noms demandés. Avec plusieurs noms, les valeurs présentes sont affichées et les noms absents n’ajoutent pas de ligne de remplacement. Une sortie non vide n’établit donc pas que toute la liste a été trouvée.

GNU printenv renvoie 0 quand tous les noms demandés existent, 1 quand au moins un manque et 2 en cas d’erreur d’écriture. D’autres erreurs d’usage peuvent également produire un échec : ne traduisez pas tout statut non nul par « variable absente ».

Vérifier une valeur vide par le statut

env QUOTING_STYLE=literal DEMO_EMPTY= printenv DEMO_EMPTY
printf 'Statut de la valeur vide : %s\n' "$?"
env -u DEMO_EMPTY printenv DEMO_EMPTY
printf 'Statut de la variable absente : %s\n' "$?"

La première consultation possède une valeur vide et réussit avec 0. La seconde ne trouve pas la variable et renvoie 1. L’apparence seule d’une ligne ne suffit pas à faire cette distinction.

La présentation peut dépendre de la version, de la destination de sortie et du style de citation. Le manuel de GNU Coreutils 9.12 décrit notamment une représentation de type shell-escape sur le terminal pour les valeurs nommées. Les exemples nécessitant une sortie littérale la demandent explicitement avec QUOTING_STYLE=literal. Le manuel officiel de printenv précise ce format et les statuts.

Distinguer une variable du shell et une variable exportée

Une affectation ne retire pas nécessairement un attribut d’export déjà présent. Pour un essai sans ambiguïté, ce sous-shell commence donc par retirer la variable de test :

(
  unset -v DEMO_LOCAL
  DEMO_LOCAL=interne
  printf 'Valeur dans Bash : %s\n' "$DEMO_LOCAL"
  printenv DEMO_LOCAL
  printf 'Statut avant export : %s\n' "$?"
  export DEMO_LOCAL
  printenv DEMO_LOCAL
)

Le premier printf affiche interne parce que Bash connaît sa variable locale au shell. La première consultation par printenv ne trouve pas cette valeur dans l’environnement reçu et renvoie 1. Après export, la consultation affiche interne. Les parenthèses limitent les changements à l’exercice.

Forme Ce qu’elle observe ou modifie
printenv NOM Lire une valeur reçue dans l’environnement du programme.
printf '%s\n' "$NOM" Afficher une valeur développée par le shell, même non exportée.
export NOM Marquer la variable du shell pour la transmettre aux programmes suivants.
env NOM=valeur programme Ajuster l’environnement d’un lancement sans changer le parent.

Les tableaux Bash et certaines variables spéciales ne deviennent pas des variables d’environnement ordinaires. Pour inspecter un nom dans Bash, declare -p NOM peut être plus adapté qu’un affichage global avec set.

Conserver des valeurs contenant des sauts de ligne avec -0

Une valeur d’environnement peut contenir des sauts de ligne. Si vous découpez une sortie uniquement sur ces caractères, vous risquez de confondre le contenu d’une valeur avec la séparation entre plusieurs valeurs. L’option GNU -0, ou --null, termine chaque élément par l’octet NUL.

Ce bloc complet utilise seulement une valeur de démonstration avec deux lignes et un saut de ligne final :

(
  set -o pipefail
  env -i QUOTING_STYLE=literal DEMO_TEXT=$'ligne1\nligne2\n' \
    /usr/bin/printenv -0 DEMO_TEXT |
    while IFS= read -r -d '' valeur; do
      printf '%q\n' "$valeur"
    done
)

Le programme doit traiter cette valeur comme un seul élément, et printf '%q' rend ses sauts de ligne visibles dans une représentation protégée pour Bash. QUOTING_STYLE=literal demande ici les données littérales à printenv, tandis que NUL sert de séparateur. Les variables d’environnement ne peuvent pas contenir cet octet dans leur valeur.

IFS=, read -r et -d '' évitent respectivement un découpage parasite, l’interprétation des barres obliques inverses et l’utilisation du saut de ligne comme séparateur. Ce consommateur est propre à Bash ; vérifiez la compatibilité des outils de toute la chaîne.

pipefail permet de conserver un échec du producteur même si la boucle finale termine normalement. Les variables lues dans ce pipeline ne sont pas à considérer comme des variables conservées ensuite dans votre shell parent.

Évitez la substitution valeur=$(printenv NOM) si vous devez conserver exactement les sauts de ligne finaux : la substitution de commande les retire. Pour un affichage humain simple, cette perte peut être acceptable ; pour des données exactes, choisissez un format et un consommateur qui les préservent.

Vérifier la présence dans un script sans afficher la valeur

Si vous voulez seulement savoir si une variable est transmise, il est inutile d’afficher son contenu. Enregistrez ce script complet dans un nouveau fichier verifier-variable.sh :

#!/usr/bin/env bash
if [ "$#" -ne 1 ] || [ -z "$1" ]; then
  printf 'Utilisation : bash verifier-variable.sh NOM\n' >&2
  exit 64
fi

if printenv -- "$1" >/dev/null; then
  printf 'Variable présente dans l’environnement : %s\n' "$1"
else
  statut=$?
  case "$statut" in
    1) printf 'Variable absente de l’environnement : %s\n' "$1" >&2 ;;
    *) printf 'Erreur de consultation pour %s : code %d\n' "$1" "$statut" >&2 ;;
  esac
  exit "$statut"
fi

Testez-le avec une valeur connue, une valeur vide et un nom retiré de l’environnement :

env DEMO_MODE=essai bash verifier-variable.sh DEMO_MODE
env DEMO_MODE= bash verifier-variable.sh DEMO_MODE
env -u DEMO_MODE bash verifier-variable.sh DEMO_MODE

Les deux premiers appels indiquent une présence et terminent avec 0. Le troisième indique une absence et termine avec 1. Le script ne révèle pas la valeur. Un nombre d’arguments incorrect ou un nom vide produit le code 64, choisi pour son propre usage.

Un autre échec de printenv conserve son statut et ses diagnostics au lieu d’être présenté comme une absence. -- évite qu’un nom commençant par un tiret soit traité comme une option de GNU printenv.

Diagnostiquer PATH et les différences entre processus

Pour lire les répertoires d’un PATH ordinaire, une entrée par ligne :

env QUOTING_STYLE=literal printenv PATH | tr ':' '\n'

Le deux-points est le séparateur de cette liste sur les systèmes de type Unix. Une entrée vide, notamment au début, à la fin ou entre deux séparateurs, désigne le répertoire courant. Ce découpage sert à la lecture humaine ; un nom de répertoire contenant lui-même un saut de ligne ne se distingue pas proprement dans une simple présentation par lignes.

Si PATH manque, vérifiez directement le statut de printenv PATH : le statut du dernier outil d’un pipeline ne décrit pas nécessairement celui du producteur.

L’environnement n’est pas une table unique de toute la machine. Un nouveau terminal, un service, une tâche planifiée ou un conteneur peut recevoir d’autres valeurs. Un printenv lancé depuis votre terminal ne lit pas directement l’environnement interne d’un service déjà en cours d’exécution ; examinez le contexte et les réglages qui lancent réellement le programme concerné.

Les règles de sudo et de l’exécution avec d’autres privilèges peuvent aussi filtrer des variables. Vérifiez les valeurs nécessaires et la configuration prévue au lieu de chercher à conserver sans distinction tout l’environnement. Pour un diagnostic partageable, limitez les noms consultés ou utilisez le test de présence sans valeur présenté plus haut.