user3151209
user3151209

Reputation: 83

How to print something to the right-most of the console in Linux shell script

Say I want to search for "ERROR" within a bunch of log files.

I want to print one line for every file that contains "ERROR".

In each line, I want to print the log file path on the left-most edge while the number of "ERROR" on the right-most edge.

I tried using:

printf "%-50s %d" $filePath $errorNumber

...but it's not perfect, since the black console can vary greatly, and the file path sometimes can be quite long.

Just for the pleasure of the eyes, but I am simply incapable of doing so. Can anyone help me to solve this problem?

Upvotes: 3

Views: 1233

Answers (1)

agc
agc

Reputation: 8406

Using bash and printf:

printf "%-$(( COLUMNS - ${#errorNumber} ))s%s" \
       "$filePath" "$errorNumber"

How it works:

  1. $COLUMNS is the shell's terminal width.

  2. printf does left alignment by putting a - after the %. So printf "%-25s%s\n" foo bar prints "foo", then 22 spaces, then "bar".

  3. bash uses the # as a parameter length variable prefix, so if x=foo, then ${#x} is 3.


Fancy version, suppose the two variables are longer than will fit in one column; if so print them on as many lines as are needed:

printf "%-$(( COLUMNS * ( 1 + ( ${#filePath} + ${#errorNumber} ) / COLUMNS ) \
          - ${#errorNumber} ))s%s"   "$filePath" "$errorNumber"

Generalized to a function. Syntax is printfLR foo bar, or printfLR < file:

printfLR() { if [ "$1" ] ; then echo "$@" ; else cat ; fi |
             while read l r ; do
                 printf "%-$(( ( 1 + ( ${#l} + ${#r} ) / COLUMNS ) \
                              * COLUMNS - ${#r} ))s%s"   "$l" "$r"
             done ;  }

Test with:

# command line args
printfLR foo bar
# stdin
fortune | tr -s ' \t' '\n\n' | paste - - | printfLR

Upvotes: 6

Related Questions