[bash] How do I iterate through lines in an external file with shell?

Possible Duplicate:
Looping through the content of a file in Bash?

I have one file with a list of names. I need to loop through all names in this file from an external file with a shell script. How can I do that?

Example files:

scripts/names.txt

alison
barb
charlie
david

scripts/script.sh

NAMES="" #names from names.txt file
for NAME in $NAMES; do
    echo "$NAME"
done

How can I explode the names.txt file into an array in a separate shell script?

This question is related to bash shell

The answer is


This might work for you:

cat <<\! >names.txt
> alison
> barb
> charlie
> david
> !
OIFS=$IFS; IFS=$'\n'; NAMES=($(<names.txt)); IFS=$OIFS
echo "${NAMES[@]}"
alison barb charlie david
echo "${NAMES[0]}"
alison
for NAME in "${NAMES[@]}";do echo $NAME;done
alison
barb
charlie
david

cat names.txt|while read line; do
    echo "$line";
done

I know the purists will hate this method, but you can cat the file.

NAMES=`cat scripts/names.txt` #names from names.txt file
for NAME in $NAMES; do
   echo "$NAME"
done

You'll be wanting to use the 'read' command

while read name
do
    echo "$name"
done < names.txt

Note that "$name" is quoted -- if it's not, it will be split using the characters in $IFS as delimiters. This probably won't be noticed if you're just echoing the variable, but if your file contains a list of file names which you want to copy, those will get broken down by $IFS if the variable is unquoted, which is not what you want or expect.

If you want to use Mike Clark's approach (loading into a variable rather than using read), you can do it without the use of cat:

NAMES="$(< scripts/names.txt)" #names from names.txt file
for NAME in $NAMES; do
    echo "$NAME"
done

The problem with this is that it loads the whole file into $NAMES, when you read it back out, you can either get the whole file (if quoted) or the file broken down by $IFS, if not quoted. By default, this will give you individual words, not individual lines. So if the name "Mary Jane" appeared on a line, you would get "Mary" and "Jane" as two separate names. Using read will get around this... although you could also change the value of $IFS