0

I have 4 files :

text1005.txt
text1007.txt
text1009.txt
text1012.txt

I create list :

FILES=$(find -type f -name "*txt")

arr=${FILES}

But when I want to print the indices, it doesn't give the good file. For example,

echo ${arr[1]}

./text1009.txt

It should've given to me the first file in the list which is text1005.txt . It will be problematic because later, I will use the $SLURM_ARRAY_TASK_ID variable , so I need the indices match with the good file.

Any suggestion?

Paillou
  • 779
  • 7
  • 16
  • 1
    `FILES` is not an array, try `mapfile -t files < <(find -type f -name "*txt"); printf '%s\n' "${files[@]}"` – Jetchisel Jul 06 '20 at 11:33
  • Thanks it works! Is there a way to not begin by the indice "0" ? I mean, when I use `printf '%s\n' "${files[1]}"` , I would to get in output the first file.. – Paillou Jul 06 '20 at 11:47
  • You need to loop through the files and add the desired number to the files, since arrays always counts from zero. – Jetchisel Jul 06 '20 at 11:49
  • I tried to look at which indice matches with which file : `for i in "${!files[@]}" ; do printf '${files[%s]}=%s\n' "$i" "${files[i]}"; done` `${files[0]}=./text1007.txt ${files[1]}=./text1009.txt ${files[2]}=./text1012.txt ${files[3]}=./text1005.txt` – Paillou Jul 06 '20 at 12:35
  • But I don't know how to put the good indice with the good file .. – Paillou Jul 06 '20 at 12:37
  • 1
    `n=1; for files in *.txt; do array[n++]=$files; done; printf '%s\n' "${array[@]}"` – Jetchisel Jul 06 '20 at 12:39
  • What's the definition of "good index with good file"? Do you want `text1009.txt` at index 1009? – Benjamin W. Jul 06 '20 at 12:39
  • What I woud like is : the indice 0 matches with the first file `text1005.txt` , the indice 1 matches with the second file `text1007.txt` etc – Paillou Jul 06 '20 at 12:43
  • 1
    1) `find` output is not sorted; 2) `a=$b` does not create an array. `FILES=$(find -type f -name '*txt'|sort); arr=($FILES); echo ${arr[1]}` – jhnc Jul 06 '20 at 13:10

1 Answers1

1

First, avoid all-caps vars.
Second,

files=$(find -type f -name "*txt")

creates a single variable, not an array -

$: echo "$files"
./text1005.txt
./text1007.txt
./text1009.txt
./text1012.txt

$:  echo "${#files[@]}"
1

To make in at array, you need parens.

files=( $(find -type f -name "*txt") )

Third, find does not implicitly sort its output.
If you need explicitly sorted output, explicitly sort your output. :)

files=( $(find -type f -name "*txt" | sort ) ) # sort has lots of options

This seems like a bit of overkill if just for the files to be lexically sorted, which is the default output for simple globbing. In your find you explicitly limit files to -type f, which is good, but since all the files in your example are *.txt (which I take to imply text files) it may be unnecessary. Let the interpreter handle it without starting three (yes, three) subprocesses.

$: files=( *txt )      # faster & easier to read
$:  echo "${files[@]}"
text1005.txt text1007.txt text1009.txt text1012.txt
$: echo "${#files[@]}"
4
$:  echo "${files[0]}"
text1005.txt
$:  echo "${files[2]}"
text1009.txt

Does that do what you want?

Paul Hodges
  • 13,382
  • 1
  • 17
  • 36