Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I have this bash script:

for opt in string1 string2 string3 ... string99
do somestuff

It works, but I would like to replace the explicit listing of my strings with a file which actually contains all the strings; something like this:

for opt in $strings
do somestuff

How should I do this?

share|improve this question
up vote 8 down vote accepted

while read VAR is probably best here, as it handles per-line input. You can redirect it from a file, e.g.:

while IFS= read -r THELINE; do
  echo "..$THELINE"
done </path/to/file

That'll give you each line prepended with ".."

For your example case:

while IFS= read -r opt; do
  #somestuff $opt
done </path/to/file

See Why is `while IFS= read` used so often, instead of `IFS=; while read..`? for explanations.

share|improve this answer
Putting cats into pipes is bad behavior from a memory management point of view. especially when using "filter" built-in commands. @rush's answer is better, and what I use on a daily basis. – David Kohen Sep 19 '12 at 14:15
It also puts the while loop into a subshell, which can cause confusing behaviour if update variable values in the loop (the values will disappear when the subshell exits) – glenn jackman Sep 19 '12 at 15:48
If somestuff includes another read, this seems not to work properly. – Raphael Feb 23 '13 at 19:04
@raphael - in what way does it not "work properly"? I just tried nested reads and it works fine. – IBBoard Feb 24 '13 at 13:52
@IBBoard See this new question. – Raphael Feb 24 '13 at 15:59
while IFS= read -r opt
done < file_with_string

See Why is `while IFS= read` used so often, instead of `IFS=; while read..`? for explanations.

share|improve this answer

The while IFS= read -r line; do ...; done < aFile is the best answer

If your strings do not contain whitespace or \[*?, you could do

for word in $(< aFile); do something; done

$(< file) is a bash feature that reads the file (like cat except without having to spawn a new process).

share|improve this answer

Why don't you use the readarray builtin (requires bash >= 4.0)?

readarray < FileNameFromWhereToLoad    # push every line of 
                                       # 'FileNameFromWhereToLoad' onto 
                                       # $MAPFILE by default

for i in $MAPFILE ; do
    echo $i
share|improve this answer
This also requires newer version of bash. – David Kohen Sep 19 '12 at 14:12
i wouldn't call bash >= 4 new (release date was February 2009)! – user1146332 Sep 19 '12 at 14:31
Since he's using 2.05a, it is newer than what the asker has. In addition, some companies have avoided GPLv3 versions of bash, so do not have it in their system. – David Kohen Sep 19 '12 at 14:36
Do you have a crystal ball around? But yes, i agree with you about your last statement, i will add the version requirement of readarray to my answer. – user1146332 Sep 19 '12 at 14:39
I didn't read that. Thanks for the hint ;) Maybe my answer is of value for somebody who will search for an answer for a similar question!? – user1146332 Sep 19 '12 at 14:56

My advice:

  declare -a LINES
  mapfile -t LINES
  for line in "${LINES[@]}"
share|improve this answer
Syntax error: bad substitution – michelemarcon Sep 19 '12 at 13:34
Works for me. @michelemarcon, is your bash 4.00 or never? – manatwork Sep 19 '12 at 13:36
GNU bash, version 2.05a.0(1)-release (arm-unknown-linux-gnu) – michelemarcon Sep 19 '12 at 13:42
That is ancient. Please specify this requirement in the question. – manatwork Sep 19 '12 at 13:46

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.