简体   繁体   中英

Format multiline command output in bash using printf

My Bash script uses printf to print output of some other commands with formatting applied, in the following manner (note the two leading spaces):

printf "  %-16s %s\n" "foo:" "$(bar)"

The two leading spaces are there, because the first line in the file is a comment, and I like to keep things nicely aligned:

# foo
  foo:            bar
  foo:            bar
  ...

This works perfectly fine for commands with one-line output. However, when the output is multiline, the output looses the formatting of the subsequent lines.

For example:

printf "  %-16s %s\n" "Contents:" "$(ls -a)"

Results in something like this:

  Contents:       .
..
foo
bar

Instead, what I am trying to achieve is multiline output, with each line formatted (in columns, if you like), which would look like this (note the lack of "header" in the subsequent lines):

  Contents:       .
                  ..
                  foo
                  bar

My understanding so far is that printf with two arguments (the first one being a string, and the other one the result of the given command) treats the second argument as a single string, which can include newline characters within. Therefore, the output is actually correctly formatted, according to what I asked printf to do, but it is not what I am looking for.

I am aware about some of the pitfalls related to parsing the output of commands like ls , which exhausts my current possibilities of solving this problem. Also, it is possible that printf is not the best facility to do this.

I am considering substituting multiline string into comma-separated list, if no solution to this problem is possible, but this would be a last resort.

What would be the best method to achieve the formatting I need?

Thanks for your help.

printf "  %-16s %s\n" "foo:" "$(bar | sed '2,$s/^/                   /g')"

You may find it difficult to apply the same print instructions to a range of commands. Also output from ls can be tedious to examine because it selects an output format depending upon environment variables.

I found the following worked well for ls on my Mac:

x=$(ls -a); 
x=${x//$'\n'/$'\n'                    }; 
printf "   %-16s %s" "Contents:" "$x" $'\n'

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM