≡ Menu

Linux/UNIX: Bash Read a File Line By Line

How do I read a file line by line under a Linux or UNIX-like system using KSH or BASH shell?

You can use while..do..done bash loop to read file line by line on a Linux, OSX, *BSD, or Unix-like system.

Syntax to read file line by line on a Bash Unix & Linux shell:

  1. The syntax is as follows for bash, ksh, zsh, and all other shells -
  2. while read -r line; do COMMAND; done < input.file
  3. The -r option passed to red command prevents backslash escapes from being interpreted.
  4. Add IFS= option before read command to prevent leading/trailing whitespace from being trimmed -
  5. while IFS= read -r line; do COMMAND_on $line; done < input.file

Here is more human readable syntax for you:

while IFS= read -r var
  echo "$var"
done < "$input"


Here are some examples:

while IFS= read line
        # display $line or do somthing with $line
	echo "$line"
done <"$file"

The same example using bash shell:

while IFS= read -r line
        # display $line or do somthing with $line
	printf '%s\n' "$line"
done <"$file"

You can also read field wise:

while IFS=: read -r f1 f2 f3 f4 f5 f6 f7
        # display fields using f1, f2,..,f7
        printf 'Username: %s, Shell: %s, Home Dir: %s\n' "$f1" "$f7" "$f6"
done <"$file"

Sample outputs:

Fig.01: Bash shell scripting-  read file line by line demo outputs

Fig.01: Bash shell scripting- read file line by line demo outputs

Bash Scripting: Read text file line-by-line to create pdf files

My input file is as follows (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

My bash script:

# Usage: Create pdf files from input (wrapper script)
# Author: Vivek Gite <Www.cyberciti.biz> under GPL v2.x+
#Input file
#Output location
# If file exists 
if [[ -f "$_db" ]]
    # read it
	while IFS='|' read -r pdfid pdfurl pdftitle
    	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"

Tip: Read from bash variable

Let us say you want a list of all installed php packages on a Debian or Ubuntu Linux, enter:

# My input source is the contents of a variable called $list #
list=$(dpkg --list php\* | awk '/ii/{print $2}')
printf '%s\n' "$list"

Sample outputs:


You can now read from $list and install the package:

# BASH can iterate over $list variable using a "here string" #
while IFS= read -r pkg
    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'

Sample outputs:

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) ***

{ 19 comments… add one }

  • Chris F.A. Johnson February 8, 2011, 6:42 pm

    The bash example is correct for all shells. The ksh example is not correct; it will strip leading and trailing whitespace.

    To demonstrate, use:

    echo ":$line:"

    on a file with leading and/or trailing whitespace on one or more .

  • Anthony Thyssen September 14, 2011, 11:35 pm

    Reading a file line by line with a single loop is fine in 90% of the cases.

    But if things get more complicated then you may be better off opening the file as a file descriptor.

    Situations such as:

    * the read of the file is only a minor aspect and not the main task, but you want to avoid opening an closing the file multiple times. For example preserving where you have read up to or avoiding file closure (network, named pipes, co-processing)

    * the file being read requires different methods of parsing, that is better done in simpler but different loops. Reading emails (header and body) is an example of this, but so is reading files with separate operational and data blocks.

    * you are reading from multiple files at the same time, and switching between different files, in a pseudo-random way. That is you never quite know whch file you will need to read from next.

  • princess anu April 4, 2012, 7:01 pm

    I have a scenario like this. I have a file which has servername, port and ipaddress

    I tried couple of ways reading these records and assigning them a field and print the output to a file like below but nothing is helpful

    servername port ipaddress
    svr1 port1 ip1
    scr2 port2 ip2
    and so on

    can someone please help me.


  • princess anu April 5, 2012, 3:20 pm

    I figured it out. May be not professional but it is working for me.

    echo -n "server name    "
    echo "port number"
    echo "-----------------------------------------"
    while read line
    echo -n "$line        "
    i=$(($num % 2 ))
    if [ $i -eq 0 ]
    echo "" #### print the new line ###
    num=`expr $num + 1`
    done< serverlist.txt


    • jl3128 August 25, 2015, 10:18 pm

      if the file is 100% predictable in each host,ip,port coming in groups of 3 you can use “paste”

      cat list.txt | paste – – –

  • Robert Edward Johnson June 10, 2012, 2:30 am


    I have a question concerning how you’d actually process individual fields of input.
    For example, let’s say you’re doing the usual

    while read LINE; do
    process the statements
    done firstbyteinq and looking at firstbyteinq with a read, but 1). the cut doesn’t seem to be doing it just to the record being read, it does it to ALL the records all at one time; 2). the read of the firstbyteinq then advances the other file one record!!!

    It seems to me there ought to be some way to “declare” the positions from a to b as fields and THEN use the while read, but I’m not sure how to do that.
    I’ll try anything. Thanks VERY much in advance.

  • Chris F.A. Johnson June 10, 2012, 4:16 pm

    princess anu, there’s no need to use arithmetic; just read the file in groups of three lines:

    while :
      read server
      read port
      read ipaddr
      : do whatever
    done < "$file"
  • Chris F.A. Johnson June 10, 2012, 4:28 pm

    A correction; you need to check that the read succeeded; checking the first should be enough:

    while :
      read server || break
      read port
      read ipaddr
      : do whatever
    done < "$file"
  • MAYANK September 6, 2012, 8:19 am

    I have scenario :

    One file which contain values like:

    another file is template which has to use values from 1st file (One value at a time, line by line )

    ARGS=ABS >> save in one file

    New file:
    ARGS=SVS >> save in another file

    Can you please help me to achive this

    • bhupesh May 14, 2014, 6:30 am

      u can use paste command if the fields are same …..and then output the records to the other file and print another.

      • bhupesh May 14, 2014, 6:56 am

        rm 3 4 5
        cat 1 | while read l
        echo “$l =” >> 3
        paste 3 2 | while read line
        echo “$line” >> 4
        awk ‘{print $1,$2,$3}’ 4 > 5

        now u can move the records line by line to another file

  • Name July 2, 2013, 1:35 pm

    echo “$line” # <— will fail if "$line" is "-n", it won't print anything at all, even an empty line.

    You should use printf builtin to work around this behavior:
    printf "%s\n" "$line"

  • Chris F.A. Johnson July 3, 2013, 11:40 am

    Some shells shells will output -n; that is what POSIX requires.

  • Steve January 28, 2014, 12:55 am

    My while/read is having an issue with the data not being printed for the last line read.
    The info is read and summed but is not being printed to the report.
    The script is reading a file with tab delimited fields, sorting on a field then reading each line while assigning the fields to var names.
    If statements determine whether the numbers are summed or if a new category is found with the previous categories data being written to the report. All categories except the last are complete in the report. The last category is left out.
    I added trouble shooting echo statements to check the workflow and they showed that the last category is being read and summed but it doesnt get printed.
    It’s as if the read gets to the last line, does the work and then doesnt know what to do with the output.
    The sorted data looks something like:

    247   an-IP   Name1
    37   another-IP   Name1
    52    more-IPs   Name2
    1562   etc   Name2
    29   etc   name3
    4   etc   name3
    The report has:
    284 Name1
    1591 Name2

    Code with troubleshooting echos and most comments deleted:

    #control vars
    cat  | sort -k3 | while read -r Count IP Name
    # Handle the first line
       if [ "Name" != "$name" -a $GT -eq 0 ]
    # The read name is different than the last line (new category)
       elif [ "$Name != $name" -a $GT -gt 0 ]
    # Write previous name and count to the report
          echo " ${name} - ${GT}" >>
    # Assign new categories values to the vars
    # New line but same category found
       else [ "$Name" == "$name"  ]
    # Increment counts of the category
          GT=`expr $GT + $Count`
  • name April 3, 2014, 9:45 am

    The read name is different than the last line (new category)

       elif [ "$Name != $name" -a $GT -gt 0 ]
    # Write previous name and count to the report
          echo " ${name} - ${GT}" >>
    # Assign new categories values to the vars
    # New line but same category found
       else [ "$Name" == "$name"  ]
    # Increment counts of the category
          GT=`expr $GT + $Count`
  • Chris F.A. Johnson May 14, 2014, 11:25 am


    cat | sort -k3 | while read -r Count IP Name

    is the same as

    sort -k3 | while read -r Count IP Name

  • Stephane August 26, 2015, 6:47 am

    It is also possible to store the elements in a bash array using the -a option

    The following example reads some comma separated values and print them in reverse order:

    while IFS="," read -a A ; do
       for ((i=${#A[@]}-1;i>=0;i--)) ; do
         echo -n "$SEP${A[i]}"
    done < input.txt
  • Jaquice Stone September 23, 2015, 1:52 pm

    Hi guys. I’m just getting started with scripting and I am needing some help reading a file into the script. This shell script below works and does what it needs to do but I have to manually input the file name for “read list”. How do I modify this script to automatically read the file. Inside the file is just a list of aix server names.

    echo ” Please input the master list you know to use”
    read list
    for i in `cat $list`
    ssh $i hostname
    ssh $i df

  • Tory November 5, 2015, 6:34 pm

    Hi all,
    I need to write a script to look for user in /etc/passwd file. The program takes user input from command line and check to see if the user that the person entered exists. If user doesn’t exist, the script sends error message. I use grep to print the user which exist. But not sure what command to use and look and if the user doesn’t exist, send error message?

Leave a Comment

   Tagged with: