0

I have an array of files underneath the immediate subdirectories:

> niis=$(find . -type f)

> echo $niis
./123_20101203/123_20101203_0002_t1_mpr_AX_MPRAGE.nii.gz ./456_20140306/456_20140306_0002_t1_mpr_AX_MPRAGE.nii.gz ./789_20160723/789_20160723_0005_t1_mpr_AX_MPRAGE.nii.gz

However, when I have a loop that creates substrings based on the array values, I only get the first entry printed out:

> for n in "${niis[@]}"
> do
>   echo $n
>   subjid=${n:2:15}
>   echo $subjid
> done

./123_20101203/123_20101203_0002_t1_mpr_AX_MPRAGE.nii.gz ./456_20140306/456_20140306_0002_t1_mpr_AX_MPRAGE.nii.gz ./789_20160723/789_20160723_0005_t1_mpr_AX_MPRAGE.nii.gz
123_20101203

How can I make sure that subjid accounts for all three of these array values? I tried switching some syntax and then I get the same output for both n and subjid.

> for n in "${niis[@]}"
> do
>   echo $n
>   subjid=${n:2:15}
>   echo $subjid
> done

./123_20101203/123_20101203_0002_t1_mpr_AX_MPRAGE.nii.gz ./456_20140306/456_20140306_0002_t1_mpr_AX_MPRAGE.nii.gz ./789_20160723/789_20160723_0005_t1_mpr_AX_MPRAGE.nii.gz
./123_20101203/123_20101203_0002_t1_mpr_AX_MPRAGE.nii.gz ./456_20140306/456_20140306_0002_t1_mpr_AX_MPRAGE.nii.gz ./789_20160723/789_20160723_0005_t1_mpr_AX_MPRAGE.nii.gz
Cyrus
  • 84,225
  • 14
  • 89
  • 153
florence-y
  • 751
  • 3
  • 8
  • 18
  • `niis` *isn't* an array. A regular variable behaves like an array with one element if you try to use array syntax. – chepner Jul 12 '20 at 19:25
  • 1
    which is to say, one solution is to do `niis=( $(....) )`. Good luck. – shellter Jul 12 '20 at 19:27
  • `niis` is a string, not an array. The syntax to assign an array woud be `niis=($(find …))` (though this causes the shell to interpret the output from `find`, which introduces robustness problems for files with irregular names) but probably storing the results in a variable is totally unnecessary here. – tripleee Jul 12 '20 at 19:28

1 Answers1

1

niis is not an array; it's a single string with embedded newlines. If you want an array, use readarray to set its value.

readarray -t niis < <(find . -type f)

However, this limited use of find is better replaced with a glob, which can accommodate file names that contain newlines.

niis=(**/*)

or if you are really concerned about filtering out non-regular files,

niis=()
for f in **/*; do
  [[ -f $f ]] && niis+=("$f")
done
chepner
  • 497,756
  • 71
  • 530
  • 681