Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Variables value gets lost in subshell

This bash script concatenates the names for jar files to a classpath (variable CP), in the while loop the value is correct but is lost in the subshell as descibed in this related question Bash variable scope

#!/bin/bash
CP="AAA"
func() {
        ls -1 | while read JAR
        do
                if [ ! -z "$CP" ]; then
                        CP=${CP}':'
                fi
                CP=${CP}${JAR}
        done
        echo $CP # <-- prints AAA
}

func

My question is, since I can't figure out which element will be the last one, how can the value be saved.

Do I actually have to save the current value (repeatedly in the loop) to a file?

EDIT:

A colleague came up with this command sequence which works well

ls | xargs echo|tr ' ' :
like image 779
stacker Avatar asked Oct 16 '25 03:10

stacker


2 Answers

The issue here is that using while in a pipeline creates a subshell, and a subshell cannot affect its parent. You can get around this in a few ways. For what you are doing now, this will suffice:

for JAR in *; do
    # Your stuff
done

Another thing to note is that you shouldn't rely on parsing ls

This also shows you ways to avoid the subshell.

like image 170
Daenyth Avatar answered Oct 18 '25 20:10

Daenyth


You might find using find a bit more versatile.

For example:

export CP=$( find /home/depesz/q/ -maxdepth 1 -type f -name '*.jar' -printf ':%p' | cut -b 2- )

Of course set of find options is dependant on what you need/want.

This one is closer to what you had previously:

export CP=$( find . -maxdepth 1 -type f -name '*.jar' -printf ':%f' | cut -b 2- )