1

I have two filenames that I would like to store in a Bash variable :

For this, I did :

$ b=$(ls Fisher_GCph_WL_XSAF_COLUMN*PESS_F*gamma_*)

I get the variable b equal to :

$ echo $b
Fisher_GCph_WL_XSAF_COLUMN2_2_PESS_F_FoM_33.22_gamma_0.071.txt
Fisher_GCph_WL_XSAF_COLUMN2_2_PESS_F_FoM_71.91_gamma_N.txt

I want to build an array of 2 elements containing the 2 filenames above.

I tried to access them by :

$d eclare -a b
$ echo ${b[0]}

returns nothing

and

$ echo ${b[1]} returns F

What to do to have an array of string where I could access directly to first or second filename by index 0 or 1 ?

halfer
  • 19,824
  • 17
  • 99
  • 186
  • 2
    Do the answers to ["Reading filenames into an array"](https://stackoverflow.com/questions/10981439/reading-filenames-into-an-array) cover your question? (Also, what shell are you using? What you describe does not match bash's normal behavior.) – Gordon Davisson Jan 09 '22 at 21:12
  • Which shell do you use? – Cyrus Jan 09 '22 at 21:18
  • 2
    Sounds like you're using zsh, not bash. – Shawn Jan 09 '22 at 21:45
  • You don't need `ls` here. The glob itself generates the two file names, which is why `ls` receives them as arguments. – chepner Jan 10 '22 at 20:23

2 Answers2

3

You just need a simple array assignment and globbing.

shopt -s nullglob
b=(Fisher_GCph_WL_XSAF_COLUMN*PESS_F*gamma_*)
konsolebox
  • 72,135
  • 12
  • 99
  • 105
  • 2
    Just to add about `shopt -s nullglob`: depending on the context, saving + restoring `nullglob` might be a good idea – Fravadona Jan 09 '22 at 23:28
1

The index notation you use is correct. The issue here b is not an array but a multiline string.

To declare a true array:

b=("Fisher_GCph_WL_XSAF_COLUMN2_2_PESS_F_FoM_33.22_gamma_0.071.txt" "Fisher_GCph_WL_XSAF_COLUMN2_2_PESS_F_FoM_71.91_gamma_N.txt")

NOTE - no comma between elements

bash treats b as an array:

declare -a b='([0]="Fisher_GCph_WL_XSAF_COLUMN2_2_PESS_F_FoM_33.22_gamma_0.071.txt" [1]="Fisher_GCph_WL_XSAF_COLUMN2_2_PESS_F_FoM_71.91_gamma_N.txt")'

Compare that to return from ls:

$ c=$(ls)
$ declare -p c
declare -- c="Fisher_GCph_WL_XSAF_COLUMN2_2_PESS_F_FoM_33.22_gamma_0.071.txt
Fisher_GCph_WL_XSAF_COLUMN2_2_PESS_F_FoM_71.91_gamma_N.txt"

In your case I would

  1. Create an intermediate file:
ls -1 > filelist

This is 'one' not 'l' - one row per file

  1. Convert file into array:
$mapfile -t b < filelist
  1. Validate b is an array:
$ declare -p b
  1. Use the array:
echo  ${b[1]}