[bash] Read a file line by line assigning the value to a variable

I have the following .txt file:

Marco
Paolo
Antonio

I want to read it line-by-line, and for each line I want to assign a .txt line value to a variable. Supposing my variable is $name, the flow is:

  • Read first line from file
  • Assign $name = "Marco"
  • Do some tasks with $name
  • Read second line from file
  • Assign $name = "Paolo"

This question is related to bash

The answer is


Many people have posted a solution that's over-optimized. I don't think it is incorrect, but I humbly think that a less optimized solution will be desirable to permit everyone to easily understand how is this working. Here is my proposal:

#!/bin/bash
#
# This program reads lines from a file.
#

end_of_file=0
while [[ $end_of_file == 0 ]]; do
  read -r line
  # the last exit status is the 
  # flag of the end of file
  end_of_file=$?
  echo $line
done < "$1"

Use IFS (internal field separator) tool in bash, defines the character using to separate lines into tokens, by default includes <tab> /<space> /<newLine>

step 1: Load the file data and insert into list:

# declaring array list and index iterator
declare -a array=()
i=0

# reading file in row mode, insert each line into array
while IFS= read -r line; do
    array[i]=$line
    let "i++"
    # reading from file path
done < "<yourFullFilePath>"

step 2: now iterate and print the output:

for line in "${array[@]}"
  do
    echo "$line"
  done

echo specific index in array: Accessing to a variable in array:

echo "${array[0]}"

The following will just print out the content of the file:

cat $Path/FileName.txt

while read line;
do
echo $line     
done

For proper error handling:

#!/bin/bash

set -Ee    
trap "echo error" EXIT    
test -e ${FILENAME} || exit
while read -r line
do
    echo ${line}
done < ${FILENAME}

#! /bin/bash
cat filename | while read LINE; do
    echo $LINE
done

Use:

filename=$1
IFS=$'\n'
for next in `cat $filename`; do
    echo "$next read from $filename" 
done
exit 0

If you have set IFS differently you will get odd results.


If you need to process both the input file and user input (or anything else from stdin), then use the following solution:

#!/bin/bash
exec 3<"$1"
while IFS='' read -r -u 3 line || [[ -n "$line" ]]; do
    read -p "> $line (Press Enter to continue)"
done

Based on the accepted answer and on the bash-hackers redirection tutorial.

Here, we open the file descriptor 3 for the file passed as the script argument and tell read to use this descriptor as input (-u 3). Thus, we leave the default input descriptor (0) attached to a terminal or another input source, able to read user input.


I encourage you to use the -r flag for read which stands for:

-r  Do not treat a backslash character in any special way. Consider each
    backslash to be part of the input line.

I am citing from man 1 read.

Another thing is to take a filename as an argument.

Here is updated code:

#!/usr/bin/bash
filename="$1"
while read -r line; do
    name="$line"
    echo "Name read from file - $name"
done < "$filename"

Using the following Bash template should allow you to read one value at a time from a file and process it.

while read name; do
    # Do what you want to $name
done < filename