Search code examples
bashdash-shell

Editing the output in a pipeline


I encountered a problem while writing my bash script

cutfiles=`find $DIR -type f |
   file -b $SAVEFILES |
   cut -c1-40 |
   sort -n | 
   uniq -c | 
   sort -nr | 
   head -10 | 
   while read -r n text; do 
      printf "  %s...%$((40-${#text}))s: " "$text"
      for ((i=0;i<$n;i++)); do 
         printf "%s" "#"
      done
      echo
   done`

Output looks like this:

  ASCII text...                           : #######
  empty...                                : ####
  Bourne-Again shell script, ASCII text...: ##
  PDF document, version 1.4...            : #

What i am trying to do is put the dots only when the file type is longer than 40 not always. Example:

  ASCII text                              : #######
  empty                                   : ####
  Bourne-Again shell script, ASCII text...: ##
  PDF document, version 1.4               : #

Is there a way to do it?


Solution

  • The awk solution of @PSkocik is very good.
    Just for the record, you can do things (slower) without awk.

    When you want to replace everything after the 37th pos when a string is longer than 40 pos, you can use

    sed 's/\(.\{37\}\).\{3\}.\+/\1.../' <<< "$text"
    

    Off-topic:
    You can replace

      for ((i=0;i<$n;i++)); do 
         printf "%s" "#"
      done
      echo
    

    with

       printf "%*.*s\n" $n $n '#' | tr ' '  '#'
    

    EDIT:
    Note that removing the cut is not possible with my solution, since the differences in strings can be after the 40th position and you want uniq lines in the output. When only the 38th pos is different you will get different output lines, so it would be better to replace the cut command with the sed command.