As of 2016-02-26, there will be no more posts for this blog. s/blog/pba/
Showing posts with label moreutils. Show all posts

combine is a Perl script from moreutils, I recently found it might be useful after I stopped introducing these nice programs from moreutils.

You can use it as in the following command usages:


combine file1 and file2
combine file1 not file2
combine file1 or file2
combine file1 xor file2

Also supports - as standard input.

Here is an example case I could thing of, say an engaged couple is getting married and they need to sort out who should be in their guest lists. They decide each of them can invite ten guests, so here is their own lists:


% cat groomslist
Bryan Shreve
Dennis Peachey
Eugene Scherer
Jessen
Jonathan Rochelle
Katherine Levin
Kay Begin
Nicholas Jarrell
Russell Bennett
Verna Butcher

% cat brideslist
Bryan Shreve
Dennis Peachey
Elizabeth Bixler
Janet Denison
Jeff Suh
Jeremy Friedman
Jonathan Rochelle
Katherine Levin
Russell Bennett
Shelley Tisdale

The first thing, they want to know who are invited by both:


% combine groomslist AND brideslist
Bryan Shreve
Dennis Peachey
Jonathan Rochelle
Katherine Levin
Russell Bennett

And the bride wants to check if her lovely fiancĂ© and husband-to-be invites some girls which he shouldn’t put them in the list:


% combine groomslist NOT brideslist
Eugene Scherer
Jessen
Kay Begin
Nicholas Jarrell
Verna Butcher

After groom passes the test, they move on to check who are invited only by one party:


% combine groomslist XOR brideslist
Eugene Scherer
Jessen
Kay Begin
Nicholas Jarrell
Verna Butcher
Elizabeth Bixler
Janet Denison
Jeff Suh
Jeremy Friedman
Shelley Tisdale

Now, they can decide if they really want to invite those people. Also since they have five common guests, therefore they can each invite more quests to fill up empty seats. If they want to edit, using vimdiff might be a good idea to merge the files.

combine does not require files to be sorted. If you want to use normal tools, for example:


% diff groomslist brideslist
3,4c3,6
< Eugene Scherer
< Jessen
---
> Elizabeth Bixler
> Janet Denison
> Jeff Suh
> Jeremy Friedman
7,8d8
< Kay Begin
< Nicholas Jarrell
10c10
< Verna Butcher
---
> Shelley Tisdale

% diff groomslist brideslist | grep ^<
...

Those files have to be sorted to get correct result.

pee is a C code from moreutils. You can do something with it like:

% pee bc bc
1+2
1+2
[Press Ctrl+D]
3
3

$ echo '1+2' | pee bc bc
3
3

pee accepts arguments as commands. It will feed those commands with the standard input it gets.

As usual for moreutils post, I wrote a Bash script, pees:

#!/bin/bash

if (($# == 0)); then
  echo "Please specify command(s) as argument(s) of $(basename "$0")."
  exit 1
fi

TMPFILE="$(mktemp)"

while read line; do echo "$line" >> "$TMPFILE"; done

for cmdargs in "$@"; do bash -c "$cmdargs" < "$TMPFILE"; done

rm "$TMPFILE"

Needless to say, pees can do the examples above. But it can also do these as pee can:

ts is a Perl script from moreutils. You use it with pipe, it receives stdout of another program. The basic idea is doing:

command | ts

It’s useful when you need to know when a program processes something. But it’s not enough for me, I wrote a Bash script ts.sh to do more.

#!/bin/bash

DATECMD='date +%H:%M:%S'

process_stdout() {
  while read line; do
    echo -e "\e[44m$($DATECMD)\e[0m $line"
  done
}

process_stderr() {
  while read line; do
    echo -e "\e[41m$($DATECMD)\e[0m $line" 1>&2
  done
}

if (( $# == 0 )); then
  process_stdout
else
  exec 3>&1
  ( bash -c "$*" | process_stdout ) 2>&1 1>&3 | process_stderr
  exec 3>&-
fi

It can timestamp stdout and stderr of a command with different color. See the following example:

http://farm2.static.flickr.com/1380/5160212248_15b5bf58b7.jpg

The timestamps on red is the stderr of emerge, the rest on blue is the stdout. This script could also be used with pipe, but it would only timestamp on stdin, which is a command’s stdout via pipe. It’s best to use it like:

ts.sh command arg1 arg2 ...

An example with shell script as command:

ts.sh while true \; do echo tik tok \; sleep 1 \; done

chronic is a Perl script from moreutils collection, runs a command quietly. It eats up the output of the command, but if the command exits with error, which is exit status does not equal to zero, then chronic would show you the output.

From its manpage, it provides a clear example how it could be useful with cron:


0 1 * * * chronic backup # instead of backup >/dev/null 2>&1

Note

I use vixin cron, I don’t need to redirect stderr to stdout, just chronic backup >/dev/null would do in the old way.

The old way, using redirection is fine, would not give you message sent to stdout since they are redirected to /dev/null, thought you would see get stderr message from log or email if you have sent up.

chronic would get you both.

I made a simple Bash script, chronic.sh:


#!/bin/bash

tmpfile="$(mktemp)"
tmpcode="$(mktemp)"

run_cmd() {
sh -c "$*"
echo "$?" > "$tmpcode"
}

exec 3>&1
( run_cmd "$@" | while read line ; do echo "1 $line" >> "$tmpfile" ; done ) 2>&1 1>&3 | while read line ; do echo "2 $line" >> "$tmpfile" ; done
exec 3>&-

exitcode=$(cat "$tmpcode")
((exitcode > 0)) && awk '
/^1 / {print substr($0, 3)}
/^2 / {print substr($0, 3) > "/dev/stderr"}
'
< "$tmpfile"

rm "$tmpfile"
rm "$tmpcode"
exit $exitcode

It stores messages into temporary file, also exit code to another temporary file. If command fails, it prints out stdout and stderr.


% ./chronic.sh "echo 'error' 1>&2 ; echo 'normal' ; grep sdfk sdk" 2>/dev/null ; echo $?
normal
2
$ ./chronic.sh "echo 'error' 1>&2 ; echo 'normal' ; grep sdfk sdk" 1>/dev/null ; echo $?
error
grep: sdk: No such file or directory
2
$ ./chronic.sh "echo 'error' 1>&2 ; echo 'normal' ; grep sdfk sdk" ; echo $?
error
normal
grep: sdk: No such file or directory
2

The test case is an error message error, then normal stdout normal, then an incorrect grep command which returns error code 2. As you can see, the order and type of messages are still intact, so is exit code.

If you use this Perl, the message order wouldn’t be the same, it groups stdout and stderr to their own group, then prints out stdout, then stderr.


% ./chronic bash -c "echo 'error' 1>&2 ; echo 'normal' ; grep sdfk sdk" ; echo $?
normal
error
grep: sdk: No such file or directory
2

The order has been changed, but they are still in right stdout/stderr.

There are few thing which can improve my script, e.g. flatening down run_cmd to just a subshell, ( sh -c "$*" ; echo "$?" > "$tmpcode" ). It would save a few lines.

I’m currently writing more about tools from moreutils collection, more will be up soon.

https://i.ytimg.com/vi/pLb8AfLbkPo/mqdefault.jpg

Cat loves sponge as you can see in this video, but if it’s soaked with water, a sponge bathing? They would run away next time they see you hiding a sponge behind you. This video provides a nice instructions, if you want to try this one-time only bathing technique:

  1. Acquire cat and remove collar.

    First step is always the hardest, they have sixth sense, they can smell your intentions!

  2. Lightly Soap with dampened cloth (warm diluted solution of cat shampoo is best), ~ praise cat throughout ~

    I doubt they really buy it.

  3. Thoroughly rinse with warm damp cloth, then

  4. Gently towel dry. (do not iron)

    I bet some owners would want to try if ironing is more efficient.

I found it’s always fun to watch cat getting bathed, though there are some cat breeds do like water. And…

Wait a minute!