Vous pouvez utiliser la boucle bash while..do..done pour lire un fichier ligne par ligne sur un système Linux, OSX, *BSD ou de type Unix en utilisant Bash, KSH ou tout autre shell de votre choix.
Niveau de difficulté | Facile |
Privilèges de la racine | Non |
Exigences | Terminal Linux |
Catégorie | Scripting shell Linux |
Conditions préalables | Bash/ksh/zsh/tcsh |
Compatibilité avec les systèmes d'exploitation | BSD-Linux-macOS-Unix-WSL |
Temps de lecture estimé | 7 minutes |
Syntaxe : Lire un fichier ligne par ligne sur un Bash Unix
La syntaxe est la suivante pour bash, ksh, zsh, et tous les autres shells pour lire un fichier ligne par ligne :
- while read -r line; do COMMAND; done
- Le site -r passée à la commande de lecture empêche les échappements de barres obliques inversées d'être interprétés.
- Ajouter IFS= avant la commande de lecture pour éviter que les espaces blancs de début et de fin ne soient coupés.
- while IFS= read -r line; do COMMAND_on $line; done
Comment lire un fichier ligne par ligne en Bash ?
Voici une syntaxe plus lisible pour l'homme :
#!/bin/bash input="/path/to/txt/file" while IFS= read -r line do echo "$line" done < "$input"
Le fichier d'entrée ($input) est le nom du fichier que vous devez utiliser par la commande read. La commande de lecture lit le fichier ligne par ligne, en assignant chaque ligne à l'attribut $line variable shell bash. Une fois que toutes les lignes ont été lues depuis le fichier, la boucle while de bash s'arrête. Le séparateur de champs interne (IFS) est défini comme une chaîne vide afin de préserver les espaces blancs. Il s'agit d'une fonctionnalité à sécurité intégrée. Le site -r est utilisée pour ne pas autoriser les antislashes à échapper à des caractères. Veuillez noter que la commande read modifie chaque ligne d'entrée en supprimant tous les caractères d'espacement de tête et de queue tels que les espaces et les tabulations lorsque IFS= est présent avant la commande read. Cependant, si vous souhaitez que les caractères soient supprimés, ne définissez pas IFS= avant la commande read. Par exemple :
#!/bin/bash input="/path/to/txt/file" ###################################### # $IFS removed to allow the trimming # ##################################### while read -r line do echo "$line" done < "$input"
Comment utiliser la substitution commande/processus pour lire un fichier ligne par ligne
La substitution de processus ou de commande ne signifie rien d'autre que d'exécuter une commande shell et de stocker sa sortie dans une variable ou de la passer à une autre commande. La syntaxe est la suivante :
while IFS= read -r line do ## take some action on $line echo "$line" done < < (command)
Dans cet exemple, exécutez la commande ps avec aux pour répertorier tous les processus, puis les imprimer ou prendre des mesures spécifiques en fonction de vos besoins :
while IFS= read -r line do ## take some action on $line echo "$line" done < <(ps aux)
Utilisation d'une chaîne de caractères ici
Ici, les chaînes de caractères sont comme les documents. Nous pouvons l'utiliser pour alimenter en données notre boucle while en bash. Par exemple :
while IFS= read -r line do # take action on $line # echo "$line" done <<< $(command) while IFS= read -r line do # take action on $line # echo "$line" done <<< $(ps aux)
Voici un exemple de script shell pour effacer ou purger les URL/images Cloudflare à partir de l'interface CLI :
## shell script to purge urls from Cloudflare ## t="10" I="/home/vivek/.data/tags.deleted.410" # input file url="" while IFS= read -r line do url="$url $line" done <<<"$(tail -${t} ${I})" [ "$url" != "" ] && ~/bin/cloudflare.purge.urls.sh "$url"
Comment utiliser un descripteur de fichier (FD) avec la commande de lecture ?
La syntaxe est simple :
input="/path/to/file" while IFS= read -r -uN line do # do something on $line echo "$line" done N< $input
Voici un exemple de script qui lit depuis le descripteur de fichier FD # 13, au lieu de l'entrée standard comme le clavier ou le fichier :
while IFS= read -r -u13 line do echo "$line" done 13<"${input}"
Exemples qui montrent comment lire un fichier ligne par ligne
Voyons quelques exemples supplémentaires sur ce sujet :
#!/bin/ksh file="/home/vivek/data.txt" while IFS= read line do # display $line or do something with $line echo "$line" done <"$file"
Le même exemple en utilisant le shell bash :
#!/bin/bash file="/home/vivek/data.txt" while IFS= read -r line do # display $line or do somthing with $line printf '%sn' "$line" done <"$file"
Lecture d'une ligne de fichier d'entrée champ par champ
Vous pouvez également lire les champs les uns après les autres. Par exemple, le fichier /etc/passwd comporte un total de sept champs, et nous pouvons les lire un par un comme suit. Tout d'abord, visualisons le fichier en utilisant la commande cat ou more :
cat /etc/passwd more /etc/passwd
Un exemple de fichier :
root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin bin:x:2:2:bin:/bin:/usr/sbin/nologin sys:x:3:3:sys:/dev:/usr/sbin/nologin sync:x:4:65534:sync:/bin:/bin/sync games:x:5:60:games:/usr/games:/usr/sbin/nologin man:x:6:12:man:/var/cache/man:/usr/sbin/nologin lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin .... .. .... vivek:x:1000:1000:vivek,,,:/home/vivek:/bin/bash systemd-coredump:x:999:999:systemd Core Dumper:/:/usr/sbin/nologin lxd:x:998:100::/var/snap/lxd/common/lxd:/bin/false nvidia-persistenced:x:127:134:NVIDIA Persistence Daemon,,,:/nonexistent:/usr/sbin/nologin sshd:x:128:65534::/run/sshd:/usr/sbin/nologin
Dans cet exemple, je vais opérer sur des champs individuels dans chaque ligne en définissant des variables supplémentaires à lire, telles que f1, f2 et ainsi de suite :
#!/bin/bash file="/etc/passwd" # # Each input line divided into seven fields separated by a colon (:) character # while IFS=: read -r f1 f2 f3 f4 f5 f6 f7 do # display fields using f1, f2,..,f7 printf 'Username: %s, Shell: %s, Home Dir: %sn' "$f1" "$f7" "$f6" done <"$file"
Fig.01 : Scripting shell Bash - lecture d'un fichier ligne par ligne - résultats de la démonstration
Scripting Bash : Lire un fichier texte ligne par ligne pour créer des fichiers pdf
Mon fichier d'entrée est le suivant (faq.txt) :
4|http://www.cyberciti.biz/faq/mysql-user-creation/|Mysql User Creation: Setting Up a New MySQL User Account 4096|http://www.cyberciti.biz/faq/ksh-korn-shell/|What is UNIX / Linux Korn Shell? 4101|http://www.cyberciti.biz/faq/what-is-posix-shell/|What Is POSIX Shell? 17267|http://www.cyberciti.biz/faq/linux-check-battery-status/|Linux: Check Battery Status Command 17245|http://www.cyberciti.biz/faq/restarting-ntp-service-on-linux/|Linux Restart NTPD Service Command 17183|http://www.cyberciti.biz/faq/ubuntu-linux-determine-your-ip-address/|Ubuntu Linux: Determine Your IP Address 17172|http://www.cyberciti.biz/faq/determine-ip-address-of-linux-server/|HowTo: Determine an IP Address My Linux Server 16510|http://www.cyberciti.biz/faq/unix-linux-restart-php-service-command/|Linux / Unix: Restart PHP Service Command 8292|http://www.cyberciti.biz/faq/mounting-harddisks-in-freebsd-with-mount-command/|FreeBSD: Mount Hard Drive / Disk Command 8190|http://www.cyberciti.biz/faq/rebooting-solaris-unix-server/|Reboot a Solaris UNIX System
Mon script bash :
#!/bin/bash # Usage: Create pdf files from input (wrapper script) # Author: Vivek Giteunder GPL v2.x+ #--------------------------------------------------------- #Input file _db="/tmp/wordpress/faq.txt" #Output location o="/var/www/prviate/pdf/faq" _writer="~/bin/py/pdfwriter.py" # If file exists if [[ -f "$_db" ]] then # read it while IFS='|' read -r pdfid pdfurl pdftitle do local pdf="$o/$pdfid.pdf" echo "Creating $pdf file ..." #Genrate pdf file $_writer --quiet --footer-spacing 2 --footer-left "nixCraft is GIT UL++++ W+++ C++++ M+ e+++ d-" --footer-right "Page [page] of [toPage]" --footer-line --footer-font-size 7 --print-media-type "$pdfurl" "$pdf" done <"$_db" fi
Lecture de la variable du shell bash
Disons que vous voulez une liste de tous les paquets php installés sur un Linux Debian ou Ubuntu, entrez :
# My input source is the contents of a variable called $list # list=$(dpkg --list php* | awk '/ii/{print $2}') printf '%sn' "$list"
Exemples de résultats :
php-pear php5-cli php5-common php5-fpm php5-gd php5-json php5-memcache php5-mysql php5-readline php5-suhosin-extension
Vous pouvez maintenant lire la liste $ et installer le paquet :
#!/bin/bash # BASH can iterate over $list variable using a "here string" # while IFS= read -r pkg do printf 'Installing php package %s...n' "$pkg" /usr/bin/apt-get -qq install $pkg done <<< "$list" printf '*** Do not forget to run php5enmod and restart the server (httpd or php5-fpm) ***n'
Exemples de résultats :
Installing php package php-pear... Installing php package php5-cli... Installing php package php5-common... Installing php package php5-fpm... Installing php package php5-gd... Installing php package php5-json... Installing php package php5-memcache... Installing php package php5-mysql... Installing php package php5-readline... Installing php package php5-suhosin-extension... *** Do not forget to run php5enmod and restart the server (httpd or php5-fpm) ***
Conclusion
Cette page explique comment lire un fichier ligne par ligne dans un script shell bash. Consultez les documentations suivantes en utilisant la commande man ou la commande help :
$ man bash
$ man ksh
$ help read
-a array | Affecte les mots lus à des indices séquentiels de la variable tableau ARRAY, en commençant par zéro. |
-d delim | Continuez jusqu'à ce que le premier caractère de DELIM soit lu, au lieu de newline. |
e | Utilisez Readline pour obtenir la ligne. |
-i text | utiliser TEXT comme texte initial pour Readline. |
-n nchars | Retourne après avoir lu NCHARS caractères plutôt que d'attendre une nouvelle ligne, mais honore un délimiteur si moins de NCHARS caractères sont lus avant le délimiteur. |
-N nchars | Retourne seulement après avoir lu exactement NCHARS caractères, à moins que EOF soit rencontré ou que la lecture s'arrête, en ignorant tout délimiteur. |
-p prompt | Affiche la chaîne PROMPT sans nouvelle ligne de fin avant de tenter de lire. |
-r | N'autorisez pas les antislashes à échapper à des caractères. |
-s | Ne pas faire écho à l'entrée provenant d'un terminal. |
-t timeout | Délai d'attente et retour d'échec si une ligne complète d'entrée n'est pas lue dans les secondes TIMEOUT. La valeur de la variable TMOUT est le délai d'attente par défaut. TIMEOUT peut être un nombre fractionnaire. Si TIMEOUT est égal à 0, read revient immédiatement, sans essayer de lire aucune donnée, et renvoie un succès uniquement si l'entrée est disponible sur le descripteur de fichier spécifié. L'état de sortie est supérieur à 128 si le délai d'attente est dépassé. |
-u fd | Lire à partir du descripteur de fichier FD au lieu de l'entrée standard. |