Bash Echo – Print One File Per Line

bashbash-expansionecho

How can I print a list of files/directories one-per-line using echo?

I can replace spaces with newlines, but this doesn't work if the filenames contain spaces:

$ echo small*jpg
small1.jpg small2.jpg small photo 1.jpg small photo 2.jpg

$ echo small*jpg | tr ' ' '\n'
small1.jpg
small2.jpg
small
photo
1.jpg
small
photo
2.jpg

I know I can do this with ls -d1, but is it also possible using echo?

Best Answer

echo can't be used to output arbitrary data anyway, use printf instead which is the POSIX replacement for the broken echo utility to output text.

printf '%s\n' small*jpg

You can also do:

printf '%s\0' small*jpg

to output the list in NUL delimited records (so it can be post-processed; for instance using GNU xargs -r0; remember that the newline character is as valid as space or any character in a filename).

Before POSIX came up with printf, ksh already had a print utility to replace echo. zsh copied it and added a -l option to print the arguments one per line:

print -rl -- small*jpg

ksh93 added a -f option to print for printf like printing. Copied by zsh as well, but not other ksh implementations:

print -f '%s\n' -- small*jpg

Note that all of those still print an empty line if not given any argument. A better println can be written as a function as:

println() {
  [ "$#" -eq 0 ] || printf '%s\n' "$@"
}

In zsh:

println() print -rC1 -- "$@"