3

I want my directory listing output in an array.

readarray x < <( ls -la )
printf "%s" ${x[@]}

So I wrote this, which works but it splits by space and not by newline. I can't find a "newline" parameter at readarray manual, so I'm kind of curious if there is a neat way to solve that request. Please do not suggest to use find (I am restricted to use ls -la).

I use bash 4.3.

Peter
  • 292
  • 2
  • 3
  • 9
  • 1
    The splitting is occurring in the printing, not in the reading I think: see [Why does my shell script choke on whitespace or other special characters?](http://unix.stackexchange.com/questions/131766/why-does-my-shell-script-choke-on-whitespace-or-other-special-characters), in particular the section `Why do I need to write "$foo"? What happens without the quotes?` – steeldriver Aug 11 '16 at 12:48
  • Possible duplicate of this : http://stackoverflow.com/questions/18884992/how-do-i-assign-ls-to-an-array-in-linux-bash – voidspacexyz Aug 11 '16 at 12:50
  • @steeldriver Thank you for the suggestion. Putting the second argument of printf into quotes seems to change things. I would accept your answer, if you add it. – Peter Aug 11 '16 at 12:56
  • @voidspacexyz No, this is not a duplicate. Please consider that I am *restricted* to use ls -la. When using the method you've linked then it would look like this: `x=($(ls -la))` which results in split words and not split lines. – Peter Aug 11 '16 at 13:17

1 Answers1

8

It does read by line, but you forgot to quote ${x[@]} which meant the split+glob operator was applied to it.

readarray x < <(ls -la)
printf %s "${x[@]}"

Or to remove the last newline character from each of those lines:

readarray -t x < <(ls -la)
printf 'line: %s\n' "${x[@]}"

Or using the split+glob operator:

IFS=$'\n' # split on newline
set -o noglob
x=($(ls -la))

(contrary to readarray -t, that method removes empty lines though (unlikely though not impossible to occur in the output of ls -la))

If you wanted to have the list of files names (including hidden ones) without the other ls -l information, you'd rather use:

shopt -s nullglob dotglob
x=(*)

Contrary to ls -a, it doesn't include . nor .. though. If you really wanted them, you'd do instead:

shopt -s nullglob
x=(.* *)
Stéphane Chazelas
  • 522,931
  • 91
  • 1,010
  • 1,501