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?

migrated from serverfault.com Jul 25 '14 at 0:55

This question came from our site for system and network administrators.

  • 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 '14 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 '14 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 '14 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. – Gordon Davisson Jul 24 '14 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! – David Tonhofer Jul 24 '14 at 20:18

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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