7

I keep a printed version of the Bash manual handy so I'm curious about any changes made to it - especially since I don't always pay attention to the packages I update. Usually locally you have the version of the manual related to the version of the software you have, and you can track changes easily.

I built this to check some sources and have a summary:

#!/usr/bin/env bash
## bashmancheck - Check different sources for date of the last updates

header="BASH manual -- Local BASH manual -- BASH repo /doc -- BASH Reference man(www)"
data="$(links -dump 'http://git.savannah.gnu.org/cgit/bash.git/tree/doc/bash.1' | grep -om 1 'Last Change.*' | cut -d ' ' -f 4,6,9) -- $(zcat /usr/share/man/man1/bash.1.gz | grep -om 1 'Last Change.*' | cut -d ' ' -f 4,6,9) -- $(links -dump 'http://git.savannah.gnu.org/cgit/bash.git/log/doc' | grep -Eom 1 '[[:digit:]]{4}-[[:digit:]]{2}-[[:digit:]]{2}') -- $(links -dump 'http://www.gnu.org/software/bash/manual' | grep -om 1 'last updated.*' | cut -d ' ' -f 3-)"

cowthink -W80 -f bud-frogs --  $header $data

It uses links and zcat to look at a specific string in the manpages source online and locally, as well as in the /doc section of the Bash repository and finally in the online reference manual. And the output looks like this:

( BASH manual -- Local BASH manual -- BASH repo /doc -- BASH Reference man(www) )
( Feb 2 2014 -- Feb 2 2014 -- 2014-02-26 -- August 22, 2012                     )
 ------------------------------------------------------------------------------- 
     o
      o
          oO)-.                       .-(Oo
         /__  _\                     /_  __\
         \  \(  |     ()~()         |  )/  /
          \__|\ |    (-___-)        | /|__/
          '  '--'    ==`-'==        '--'  '

Yet I wish I had pairs of item and date each on a line, like so:

BASH manual: Feb 2 2014
Local BASH manual: Feb 2 2014
BASH repo /doc: 2014-02-26
BASH Reference man(www): August 22, 2012

But for that I would need to change line after I concatenate the item and its date - and I can't make happen it with cowsay/cowthink. And this explains why I have designed the script like it is. The two variables are just there to help me out with formatting but have no bearing on it at execution. It just so happens that the header and data variables are less than 80 columns wide each and the command ouput is set to 80 columns for that purpose. I also used cut to shorten the dates for them to display on one line instead of just using grep -o like I was initially doing. I arbitrarily used some characters(double dashes) for formatting - which is just crude.

Can you use newlines with something like cowsay? Is there a (better) way to do this?

3 Answers3

7

In order to make the nice bubble, cowsay trims all whitespaces by default. This implies line breaks. If you pass two line breaks in a row, cowsay prints both of them.

Try

cowsay "lala
lala"

vs.

cowsay "lala

lala"

The first will output lala lala in a bubble, the latter will output

lala

lala

This is not a shell related behavior, this is just cowsay :)

If you do not like this, you need the -n switch. It prevents word wrapping completely and therefore allows arbitrary whitespace characters.

Unfortunately, the following command does not work as excepted:

cowsay -n "lala
lala"

Because cowsay does in my version not allow passing a message as argument while -n option is given. But

echo "lala
lala" | cowsay -n

works as a charm.

So for your problem, if you don't like the double \n in your output, change the command to

(echo "BASH manual - $(links -dump 'http://git.savannah.gnu.org/cgit/bash.git/tree/doc/bash.1' | grep -om 1 'Last Change.*')"; echo "Local BASH manual - $(zcat /usr/share/man/man1/bash.1.gz | grep -om 1 'Last Change.*')"; echo "BASH repo /doc: $(links -dump 'http://git.savannah.gnu.org/cgit/bash.git/log/doc' | grep -Eom 1 '[[:digit:]]{4}-[[:digit:]]{2}-[[:digit:]]{2}')"; echo "BASH Reference man(www): $(links -dump 'http://www.gnu.org/software/bash/manual' | grep -om 1 'last updated.*')") \
| cowthink -f tux -n
Phil
  • 170
1

This is not a problem with cowsay. It's how shells deal with newlines in parameters: They are treated like any whitespace. Try out echo $(ls): All files are output in a single line, even though ls does output newlines.

Fortunately, you can pass data to cowsay via stdin:

(echo "header line"; links ...; links ...; links...) | \
    cowsay -W80 -f bud-frogs
daniel kullmann
  • 9,527
  • 11
  • 39
  • 46
  • Oh, but I thought in cowsay options -- what I put after -- was stdin? I guess I wasn't clear. I would have preferred to present the whole thing as combos item date \n i.e. Bash manual date newline etc. –  Jun 01 '14 at 09:27
  • No, what comes on the command line is not stdin. – daniel kullmann Jun 01 '14 at 12:00
  • I guess it's really a good thing I keep the manual handy then! Thank you! –  Jun 01 '14 at 20:02
1

After considering the answer, I was able to do what I wanted to do in the first place by adding newline sequences and passing the whole thing to cowthink's stdin:

#!/usr/bin/env bash
## bashmancheck - Check different sources for date of the last updates

(echo -e "BASH manual - $(links -dump 'http://git.savannah.gnu.org/cgit/bash.git/tree/doc/bash.1' | grep -om 1 'Last Change.*')\n"; echo -e "Local BASH manual - $(zcat /usr/share/man/man1/bash.1.gz | grep -om 1 'Last Change.*')\n"; echo -e "BASH repo /doc: $(links -dump 'http://git.savannah.gnu.org/cgit/bash.git/log/doc' | grep -Eom 1 '[[:digit:]]{4}-[[:digit:]]{2}-[[:digit:]]{2}')\n"; echo -e "BASH Reference man(www): $(links -dump 'http://www.gnu.org/software/bash/manual' | grep -om 1 'last updated.*')") \
| cowthink -W80 -f tux

 ______________________________________________________________ 
( BASH manual - Last Change: Sun Feb 2 16:21:40 EST 2014       )
(                                                              )
( Local BASH manual - Last Change: Sun Feb 2 16:21:40 EST 2014 )
(                                                              )
( BASH repo /doc: 2014-02-26                                   )
(                                                              )
( BASH Reference man(www): last updated August 22, 2012        )
 -------------------------------------------------------------- 
   o
    o
        .--.
       |o_o |
       |:_/ |
      //   \ \
     (|     | )
    /'\_   _/`\
    \___)=(___/
  • Pretty sure I had tried piping the data like the contributor explained in his answer. As I was distracted, I most likely forgot the -e. As I didn't get what I wanted, I assumed this was the same as passing the data with a parameter to cowthink i.e. both didn't seem to allow for a newline. It's a good lesson for the beginner that I am... Always double check, go back to the basics and, obviously, to the manual. –  Jun 01 '14 at 22:45