How to separate command output to individual lines

Instead of ill-advisedly putting ls output in a variable and then echoing it, which removes all the colors, use

ls -a1

From man ls

       -1     list one file per line.  Avoid '\n' with -q or -b

I don't advise you do anything with the output of ls, except display it :)

Use, for example, shell globs and a for loop to do something with files...

shopt -s dotglob                  # to include hidden files*

for i in R/*; do echo "$i"; done

* this won't include the current directory . or its parent .. though


If the output of the command contains multiple lines, then quote your variables to preserve those newlines when echoing:

echo "$list"

Otherwise, the shell will expand and split the variable contents on whitespace (spaces, newlines, tabs) and those will be lost.


While putting it in quotes as @muru suggested will indeed do what you asked for, you might also want to consider using an array for this. For example:

IFS=$'\n' dirs=( $(find . -type d) )

The IFS=$'\n' tells bash to only split the output on newline characcters o get each element of the array. Without it, it will split on spaces, so a file name with spaces.txt would be 5 separate elements instead of one. This approach will break if your file/directory names can contain newlines (\n) though. It will save each line of the command's output as an element of the array.

Note that I also changed the old-style `command` to $(command) which is the preferred syntax.

You now have an array called $dirs, each bof whose elements is a line of the output of the previous command. For example:

$ find . -type d
.
./olad
./ho
./ha
./ads
./bar
./ga
./da
$ IFS=$'\n' dirs=( $(find . -type d) )
$ for d in "${dirs[@]}"; do
    echo "DIR: $d"
  done
DIR: .
DIR: ./olad
DIR: ./ho
DIR: ./ha
DIR: ./ads
DIR: ./bar
DIR: ./ga
DIR: ./da

Now, because of some bash strangeness (see here), you will need to reset IFS back to the original value after doing this. So, either save it and reasign:

oldIFS="$IFS"
IFS=$'\n' dirs=( $(find . -type d) ) 
IFS="$oldIFS"

Or do it manually:

IFS=" "$'\t\n '

Alternatively, just close the current terminal. Your new one will have the original IFS set again.

Tags:

Bash

Scripts