0

In my folder I have following files:

roi_1_Precentral_L/
roi_1_Precentral_L_both.fig
roi_1_Precentral_L_left.fig
roi_1_Precentral_L_right.fig
roi_1_Precentral_L_slice.fig
roi_2_Precentral_R/
roi_2_Precentral_R_both.fig
...
roi_116_Vermis_10/
roi_116_Vermis_10_both.fig
roi_116_Vermis_10_left.fig
roi_116_Vermis_10_right.fig
roi_116_Vermis_10_slice.fig

I use following script to obtain a desired prefix of the filename for each of all 116 types:

for iroi in `seq 1 116`;
do
    d=roi_${iroi}_*/
    d2=${d:0:-1}         # <-- THIS LINE IS IMPORTANT
    echo $d2
done;

Desired output for iroi=1:

$ roi_1_Precentral_L

Actual output:

$ roi_1_Precentral_L roi_1_Precentral_L_both.fig roi_1_Precentral_L_left.fig roi_1_Precentral_L_right.fig roi_1_Precentral_L_slice.fig

How can I avoid shell expansion in the emphasized line of code to make desired output?

2 Answers2

2

If you assign to an array, the glob will be expanded on the first line, not later as of the echo as was the case with your original code.

d=( "roi_${iroi}_"*/ )
d2=${d:0:-1}            # Note that this only works with new bash. ${d%/} would be better.
echo "$d2"

If you expect multiple directories, "${d[@]%/}" will expand to the full list, with the trailing / removed from each:

d=( "roi_${iroi}_"*/ )
printf '%s\n' "${d[@]%/}"

With respect to avoiding unwanted expansions -- note that in the above, every expansion except for those on the right-hand side of a simple (string, not array) assignment is in double quotes. (Regular assignments implicitly inhibit string-splitting and glob expansion -- though it doesn't hurt to have quotes even then! This inhibition is why ${d:0:-1} was removing the / from the glob expression itself, not from its results).

Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
0

Answer to Question

If you wanted, you could quote to avoid expansion of * in $d ...

d=roi_${iroi}_*/
d2="${d:0:-1}"
echo $d2

... but then you could directly write ...

d2="roi_${iroi}_*"
echo $d2

... and the output would still be the same as in your question.

Answer to Expected Output

You could do the expansion in an array and select the first array entry, then remove the / from that entry.

for iroi in {1..116}; do
    d=(roi_"$iroi"_*/)
    d2="${d[0]:0:-1}"
    echo "$d2"
done

This matches only directories and prints the first directory without the trailing /.

Socowi
  • 25,550
  • 3
  • 32
  • 54
  • "*The `*` is already expanded in the line `d=roi_${iroi}_*/`.*" -- this is completely, utterly false. The `*` is assigned as a literal, since the right-hand side of string assignments has string-splitting and glob expansion suppressed. Run `d=/*; declare -p d` and you'll see `declare -- d="/*"` as output; no expansion took place. – Charles Duffy Jun 21 '18 at 20:32
  • @CharlesDuffy You are right. Thanks for the hint. It's always nice to (re)learn something when giving answers. – Socowi Jun 21 '18 at 20:36