This is why you never try to parse the output of ls
. ls
is designed to print to a terminal not to be used in scripts or to be parsed, there are other tools for that. You are also making it more complex yourself since you are using the -l --time-style=long-iso
options but then your desired output is only the file name.
To get the list of files and directories in the current directory into a variable, the easiest way is to just use globs:
$ ls
test1.txt test2.txt 'test space.txt'
$ files=( * )
$ echo "Files: ${files[@]}"
Files: test1.txt test2.txt test space.txt
$ echo "The third file is '${files[2]}'"
The third file is 'test space.txt'
To have the file names quoted, do:
$ printf '"%s"\n' "${files[@]}"
"test1.txt"
"test2.txt"
"test space.txt"
As you can see, the $files
array holds all of the files, with each of them stored as an element in the array. See here for a description of how bash arrays work, but briefly, you can list the entire array using ${array[@]}
and individual entries using ${array[N]}
where N
is a number between 0
(the first element of the array) and X-1 where X is the number of elements in the array. In the example above, we have 3 elements in $files
, so you have ${files[0]}
, ${files[1]}
and ${files[2]}
.
Note that this approach even works with files whose name contains a newline (\n
):
$ touch 'a file with a '$'\n''newline!'
$ ls
'a file with a '$'\n''newline!' test1.txt test2.txt 'test space.txt'
$ files=( * )
$ echo "File is: ${files[0]}"
File is: a file with a
newline!
Now, if you also want to keep the file's modification date (which is not what your output shows, but is what I think your awk
is attempting to do), you can do something like this:
$ files=( * )
$ for file in "${files[@]}"; do
date=$(stat -c '%y' -- "$file" | cut -d ' ' -f1)
printf 'Date: %s File: "%s"\n' "$date" "$file"
done
Date: 2023-08-15 File: "a file with a
newline!"
Date: 2023-08-15 File: "test1.txt"
Date: 2023-08-15 File: "test2.txt"
Date: 2023-08-15 File: "test space.txt"