Shell hacks

Or How To Illustrate the Power Of UNIX.

The Shell I use is, of course, GNU Bash. tcshers and zshers may rot in hell. >=L

Mass conversion

The following converts all images in gif format to xpm format (bash, uses perl):

for i in *.gif; do perl -e "\$n=\"$i\"; \$a=\"$i.xpm\"; \$a =~ s/\.gif//gi;
\$parm=\"convert \$n \$a\"; print \"\$parm\\n\"; \`\$parm\`;"; done
    

I used it to convert all tigert's (utterly cool) GNOME icons to .xpms before they were provided with distribution.

So why it's so hairy?

  1. It uses shell "double quotes" in perl string - I want to expand $i in middle of the thing. However, I don't want it to expand anything else in the Perl code, so I backslashify everything.
  2. It uses Perl just to trim the ".gif" extension off. basename(1)? What's that?
  3. I know that convert can do it all by itself, but I don't know how... convert(1) manpage is huge.

Replacement of killall(1)

kill `ps | grep "timidity" | perl -ane 'print @F[0]," ";'`
    

... will STOP THAT DAMNED MUSIC! Advantages? Well... you can just change the "kill" to "renice -n 20", and lo, timidity will have less priority...

Lowercasify filenames

for i in *; do mv $i `echo $i | tr 'A-Z' 'a-z'`; done
    

I had had need for such hack for long time. When I wanted to make one newbie very happy, I made this hack in a few seconds. Bugs: This doesn't use Perl.

Find all executables that use certain library

for i in *; do if [ "0" != `ldd $i | grep -c 'libc.5' -` ]; then echo
"$i"; fi; done 2> /dev/null
    

This finds all executables that use libc.5.so... change the parameter to grep in order to make it look for other libraries.

This is good for cleaning up programs that use certain shared library. (I nuked csound using this. just change 'libc.5' to 'csound' and 'echo' to 'rm'...)

Bugs: Doesn't use perl, either.

Send mail to all users of the machine you're logged on

mail `perl -F: -ane 'print @F[0], " ";' /etc/passwd`
    

Good. It uses Perl, not that sissy AWK everyone wants to use. This is another hack in the vein of "needed to help a newbie and found a solution in three minutes".

Using this thing is a surefire way of pissing everyone off and getting the root's wrath on your neck.

Conversion, take two (the boring way)

for i in *.gif; do convert $i `basename $i .gif`.xpm; done
    

Yes, it can be done in more boring way.

Bugs: Doesn't use Perl.

Better yet, use mogrify(1).

Lowercasify filenames, first letter capitalized

for i in *; do mv $i `echo $i | perl -pe '$_ = "\L\u$_\E";'`; done
    

Could be improved with "use locale".

Bugs: \r is not needed in the end of the substitution string. =)

Add some date anchors

perl -i.bak -pe 'if(/^<H2>(\d\d?)\.(\d\d?)\.(\d\d\d\d)<\/H2>$/) \
  { $anch = sprintf("%02d%02d%04d",$1,$2,$3); \
  $_ = "<A NAME=\"$anch\"><H2>$1.$2.$3</H2></A>\n"; }'  filename.html
    

That was supposed to go into one line, as usual.

Strange Days used to have all dates as <H2>1.2.3456</H2> format. This one adds A NAME elements that correspont to the date (The above would turn to <A NAME="01023456"><H2>1.2.3456</H2></A>)

NOTE: Above is Heretic Style. To be Pure by Heart, you need to change the above to generate code like <H2><A NAME="01023456">1.2.3456</A></H2>...

Spoil the spammer's joy

What a spammer said:

... our official website address is mathematically encrypted. In other words, by using a proprietary, extremely-complex, mathematical formula our website's address looks something like this in your favorite browser's window.

http://354267876296/001/652/8876/index.htm

Here's the clue:

perl -MSocket -e "print inet_ntoa(pack('N','354267876296'));"
    

Replace the number accordingly.

Last time I checked, the inet_ntoa and inet_aton C library calls were as far from proprietary as you could get - in fact, those were in the Berzerkeley C libraries long before the WWW (and UBE).

Well, the companies that are stupid enough to spam will believe that rubbish and spam away. ::sigh::

Find filenames that are longer than limit

This checks if files underneath current directory are longer than 32 characters:

for i in `find . -type f`; do
  declare f=`basename $i`;
  declare l=`echo $f | wc -c`;
  declare t=`expr $l '>' 32`;
  if [ $t == 1 ]; then
    echo $i;
  fi;
done
    

Everything on the same line, as usual.

Damn. Does anyone know a way of using nested `...` expressions? in the above hack, I needed to do that with declare.

Hairy way to chomp last byte out of file

head -c `wc -c FILE | perl -wape '$_=eval $F[0] - 1'` FILE > FILE2
    

Perl's chomp is for Wimps. True hackers *do* make heads and tails out of things!

Neater ways to do the same

Just for the sake of fairness, we use either Perl or Shell, but not both.

First, shell:

echo -ne `cat FILE` > FILE2
    

Then, Perl:

perl -pe 'chomp;' FILE > FILE2
    

Waiting for respawn

I was once having problems with Apache that kept respawning. Well, this hack alerts if the indians are attacking.... Replace the program name (and text =) if you want to monitor for something else.

while true; do
  if [ `ps ax | grep -c '/usr/sbin/apache'` != 0 ]; then
    echo -e '\007\007Run for the hills!';
  fi;
  sleep 10;
done
    

[Index] [Up] [Main] [Weyfour WWWWolf]

Last modified: Wed Mar 8 01:10:13 EET 2000