[luv-main] bash: preserving newlines when storing output in variables.

I couldn't google for this. How do I preserve line breaks when assigning the result of something to a variable? aspiers@cape:~/tmp/horror$ ls -1 file1 file2 file3 aspiers@cape:~/tmp/horror$ echo -e $(ls -1) file1 file2 file3 There must be something better than this: aspiers@cape:~/tmp/horror$ echo -e $(ls -1| awk '{print $0,"\\n"}') file1 file2 file3

On 11/11/2011, at 17:38, Andrew Spiers <7andrew@gmail.com> wrote:
I couldn't google for this. How do I preserve line breaks when assigning the result of something to a variable?
aspiers@cape:~/tmp/horror$ ls -1 file1 file2 file3 aspiers@cape:~/tmp/horror$ echo -e $(ls -1) file1 file2 file3
can do: e=$(ls) printf "%b" "$e"

On Nov 11, 2011 5:39 PM, "Andrew Spiers" <7andrew@gmail.com> wrote:
I couldn't google for this. How do I preserve line breaks when assigning the result of something to a variable?
aspiers@cape:~/tmp/horror$ ls -1 file1 file2 file3 aspiers@cape:~/tmp/horror$ echo -e $(ls -1) file1 file2 file3
There must be something better than this:
aspiers@cape:~/tmp/horror$ echo -e $(ls -1| awk '{print $0,"\\n"}') file1 file2 file3
Does this help? # export IFS=" " Note that you need to hit enter after the first double quote. Marcus

On 2011-11-11 17:38, Andrew Spiers wrote:
I couldn't google for this. How do I preserve line breaks when assigning the result of something to a variable?
aspiers@cape:~/tmp/horror$ ls -1 file1 file2 file3 aspiers@cape:~/tmp/horror$ echo -e $(ls -1) file1 file2 file3
There must be something better than this:
aspiers@cape:~/tmp/horror$ echo -e $(ls -1| awk '{print $0,"\\n"}') file1 file2 file3
Parsing ls output is *bad*! mattcen@tony:tmp$ touch a b c "file with spaces" mattcen@tony:tmp$ ls a b c file with spaces typescript mattcen@tony:tmp$ files=$(for file in *; do printf "%s\n" "$file"; done) mattcen@tony:tmp$ echo $files a b c file with spaces typescript mattcen@tony:tmp$ echo "$files" a b c file with spaces typescript mattcen@tony:tmp$ Note that the former "echo" doesn't have quotes around the variable name, and therefore doesn't honour the newlines. -- Regards, Matthew Cengia

On 2011-11-11 18:29, Matthew Cengia wrote:
mattcen@tony:tmp$ touch a b c "file with spaces" mattcen@tony:tmp$ ls a b c file with spaces typescript mattcen@tony:tmp$ files=$(for file in *; do printf "%s\n" "$file"; done)
Alternatively, now I think about it more, this will also work: files=$(find . -maxdepth 1 -printf "%f\n") -- Regards, Matthew Cengia

Matthew Cengia wrote:
mattcen@tony:tmp$ files=$(for file in *; do printf "%s\n" "$file"; done)
Ahem. If you can guarantee bash, I humbly suggest using an array. The syntax is something like xs=(*.mp3) # array of glob matches printf '"%s"\n' "${xs[@]}" # example use thereof This is more robust than converting it to a stream and back, because inherently streams must be delimited, and the only bytes you can safely delimit unix dirents with are NULL and '/' -- the latter being used already within paths. PS: OK technically you could serialize to a stream using length-counting instead a la tar, but that's kind of obtuse in this context. PPS: mattcen's loop is not needed, as printf is variadic (at least in GNU): xs=$(printf %s\\n *)

Thank you so much everyone for your help. I did indeed mean to use ls -1 purely as an example of a command that produces output with newlines. It was Hannah's suggestion That saw me straight. Cheers!

On Fri, 11 Nov 2011, Trent W. Buck wrote:
Matthew Cengia wrote:
mattcen@tony:tmp$ files=$(for file in *; do printf "%s\n" "$file"; done)
Ahem. If you can guarantee bash, I humbly suggest using an array. The syntax is something like
xs=(*.mp3) # array of glob matches printf '"%s"\n' "${xs[@]}" # example use thereof
Hah! Where in the documentation does it specify that printf prints lines for each arg not sucked up by format strings, eg: printf "%s - %s" 1 2 3 1 - 2 3 - ? That's kinda neat, but kinda dangerous and contrary to the printf() I'm used to (which just ignores extra args and segfaults if there aren't enough of them). -- Tim Connors

On 2011-11-12 20:13, Tim Connors wrote:
On Fri, 11 Nov 2011, Trent W. Buck wrote:
Matthew Cengia wrote:
mattcen@tony:tmp$ files=$(for file in *; do printf "%s\n" "$file"; done)
Ahem. If you can guarantee bash, I humbly suggest using an array. The syntax is something like
xs=(*.mp3) # array of glob matches printf '"%s"\n' "${xs[@]}" # example use thereof
Hah!
Where in the documentation does it specify that printf prints lines for each arg not sucked up by format strings, eg:
From the Bash manpage, in the printf section: The format is reused as necessary to consume all of the arguments. Alternatively, for /usr/bin/printf, 'info coreutils "printf invocation"' shows: * The FORMAT argument is reused as necessary to convert all the given ARGUMENTs.
printf "%s - %s" 1 2 3 1 - 2 3 -
?
That's kinda neat, but kinda dangerous and contrary to the printf() I'm used to (which just ignores extra args and segfaults if there aren't enough of them).
I don't see any danger; if the *expected* behaviour was that of /usr/bin/prinf and Bash's inbuild printf, then yes, perhaps printf(3) can become dangerous, but any C programmer who has written anything more complex than a Hello World program should probably know better :). -- Regards, Matthew Cengia

On Sat, 12 Nov 2011, Matthew Cengia wrote:
On 2011-11-12 20:13, Tim Connors wrote:
On Fri, 11 Nov 2011, Trent W. Buck wrote:
printf '"%s"\n' "${xs[@]}" # example use thereof
Hah!
Where in the documentation does it specify that printf prints lines for each arg not sucked up by format strings, eg:
From the Bash manpage, in the printf section:
The format is reused as necessary to consume all of the arguments.
Alternatively, for /usr/bin/printf, 'info coreutils "printf invocation"' shows:
Fricking GNU and insisting on deprecating the perfectly usable man instead of the perfectly unusable info (and slightly less unusable pinfo). /rant (I didn't see it in the bash manpage, because I thought it would be safer to look at the printf manpage) -- Tim Connors

On 2011-11-12 20:35, Tim Connors wrote:
Fricking GNU and insisting on deprecating the perfectly usable man instead of the perfectly unusable info (and slightly less unusable pinfo).
As an aside, you may or may not be aware that you can pipe info output to your viewer of choice for a less bad experience: info coreutils 'printf invocation' | less
/rant (I didn't see it in the bash manpage, because I thought it would be safer to look at the printf manpage)
-- Regards, Matthew Cengia

On 2011-11-11 17:38, Andrew Spiers wrote:
I couldn't google for this. How do I preserve line breaks when assigning the result of something to a variable?
aspiers@cape:~/tmp/horror$ ls -1 file1 file2 file3 aspiers@cape:~/tmp/horror$ echo -e $(ls -1) file1 file2 file3
However, if I've misunderstood and 'ls' is just for use in your example, then take my quoting of echo in my earlier email: echo -e "$(ls -1)" Should do what you want. -- Regards, Matthew Cengia
participants (6)
-
Andrew Spiers
-
hannah commodore
-
Marcus Furlong
-
Matthew Cengia
-
Tim Connors
-
Trent W. Buck