objectif
Lire un fichier ligne par ligne en Bash sans casser les espaces, sans interpréter les backslashes, et sans perdre les variables du shell à cause d’un pipe qui crée un subshell.
code minimal
# boucle sûre: pas de subshell, pas de split/globbing accidentel
while IFS= read -r line; do
printf '-> %s\n' "$line"
done < "./liste.txt"
utilisation
# accumuler dans un tableau (readarray/mapfile) sans sauts de ligne finaux
mapfile -t LIGNES < "./liste.txt"
printf 'count=%d first=%s\n' "${#LIGNES[@]}" "${LIGNES[0]}"
# parcourir la sortie d'une commande SANS subshell (process substitution)
count=0
while IFS= read -r user; do
((count++))
done < <(cut -d: -f1 /etc/passwd)
echo "users: $count"
# lire des lignes qui peuvent commencer par des espaces ou contenir des backslashes
while IFS= read -r line; do
case "$line" in
''|'#'*) continue ;; # ignorer vides et commentaires
esac
printf '%s\n' "$line"
done < "./config.list"
# traiter un fichier potentiellement sans newline final (boucle robuste)
# (le "|| [ -n "$line" ]" garantit la dernière ligne)
while IFS= read -r line || [ -n "$line" ]; do
echo "$line"
done < "./data.txt"
variante(s) utile(s)
# traiter des chemins avec NUL (find -print0) en toute sécurité
while IFS= read -r -d '' path; do
printf 'file: %s\n' "$path"
done < <(find . -type f -name "*.log" -print0)
# lire deux colonnes séparées par tabulation, même si les colonnes contiennent des espaces
while IFS=$'\t' read -r col1 col2; do
printf '1=%s 2=%s\n' "$col1" "$col2"
done < "./data.tsv"
# limiter le nombre de caractères lus (ex: clés fixes)
while IFS= read -r -n 16 key; do
printf 'key=%s\n' "$key"
done < "./keys.bin"
# normaliser CRLF -> LF "à la volée" (fichiers Windows)
while IFS= read -r line; do
line="${line%$'\r'}"
printf '%s\n' "$line"
done < "./win.txt"
# mapfile avec délimiteur NUL (flux -print0)
mapfile -d $'\0' -t FILES < <(find . -type f -name "*.json" -print0)
printf 'json files: %d\n' "${#FILES[@]}"
notes
- utilisez toujours
IFS=etread -rpour empêcher le découpage sur espaces et l’interprétation des backslashes. - évitez
cat fichier | while read ...; do ...; donequi exécute la boucle dans un subshell (variables perdues). Préférez la redirection< fichierou la substitution de processus< <(commande). - pour des flux NUL-terminés (sorties
-print0), ajoutez-d $'\0'àreadoumapfile. - si vos données ne sont pas des “vraies lignes” (multilignes, CSV complexes), utilisez un parseur dédié (awk/csvkit/Python).