I have a bash script which seems to lose the value of the readonly constant after the first time thru the for-in loop. For example:

readonly DIR="./groups/"
for output in "${array[@]}"
   catstring+="$DIR$output "
printf "$catstring"
cat $catstring > outputfile

The array has a bunch of names in it like: file1 file2 file3, etc.

The output from the printf statement is "./groups/file1 file2 file3". What I'm expecting is "./groups/file1 ./groups/file2 ./groups/file3".

Why is bash losing the value of $DIR after the first time thru the for-in loop?

  • 3
    I'm guessing your loop is only looping once. "${array[@]}" is evaluating to "file1 file2 file3" not file1 file2 file3 so there is a single (quoted) item to loop over.
    – DerfK
    Jul 24, 2014 at 18:42
  • Is this the actual script you are using, or is this just an example? My guess is that your actual script is more complicated and you are having the classic subshell issue. A subshell is sometimes used when you don't expect it, and variables set in the subshell aren't returned to the parent shell.
    – Zoredache
    Jul 24, 2014 at 18:49
  • 1
    @DerfK: I think you're right about it only looping over once. That must be what's happening.
    – Pretzel
    Jul 24, 2014 at 19:43
  • 2
    If double-quotes around the array reference are causing trouble, I'm pretty sure there's something wrong with how the array is being constructed; removing the double-quotes should not be necessary. I'd concentrate on figuring out what's building the array wrong. Jul 24, 2014 at 20:16
  • 1
    I have 4.2.47. But it's really not the quotes. Quoteless unset x; declare -A x ; x[0]=a ; x[1]=b ; x[2]="c d" ; for y in ${x[@]}; do echo $y; done erroneously yields 4 lines; Quoted unset x; declare -A x ; x[0]=a ; x[1]=b ; x[2]="c d" ; for y in "${x[@]}"; do echo $y; done correctly yields three lines. HOWEVER!! If you managed to put all the elements into the FIRST element of the array, one would EXACTLY get your problem. Ah-hah! Jul 24, 2014 at 20:18

1 Answer 1


You've most likely captured the file list with something like this:

array=$(ls file* )
array="$(ls file*)"

# array looks like:
# array[0]="file1 file2 file3"

You can capture as multiple indices in an array like this instead, using an extra '(' and ')'

array=( $(ls file*) )

# array looks like:
# array[0]="file1"
# array[1]="file2"
# array[2]="file3" 

and then your code will work

or perhaps you used 'read' to read the values:

ls > files.txt
read array < files.txt

then you want to use 'read -a' instead

read -a < files.txt

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .