Shell Hacks and Examples

I am a fan of the command line. What it really comes down to is efficiency. I'm the type of guy who would rather spend an hour learning to use a tool that will automate a task than make a thousand "easy to use" but tedious clicks in a GUI. Naturally, GUI's have their place, but I generally prefer command line methods. They're so much more versatile.

At my job as a Sys Admin, I once had to help someone who had a problem where Photoshop for Windows saved a bunch of images but refused to re-open them. Other programs could open them just fine, and once you resaved the files, Photoshop wouldn't have any problem at all. I described my diagnosis of the problem to the user and explained that we should open and save the dozen or so files using another program. At my Linux box, with the user looking over my shoulder, I su'd to them, went to their home directory, and then did something like the following: "mkdir bad; mv *.jpg bad; cd bad" and then "for i in *.jpg; do convert $i ../$i; done". Two seconds later, I told them that everything should be working now, and they said, "What? You didn't do anything." That's how I felt, too. It's a good feeling.

So here you'll find a bunch of one or two liners that I consider either essential or very cool. My examples and descriptions are meant to convey the gist of the technique. If you research the tools used here, you should be able to adapt the examples to many other applications.


SSH-ing with another environment
Say you want to be able to type "work" and ssh to remotehost with a slightly different environment than normal. In this example we'll assume you want to cd to /var/www/html/abcd/efgh/ijkl automatically. Create a file on remotehost named .bashrc-work and add ". $HOME/.bashrc" and "cd /var/www/html/abcd/efgh/ijkl" to it. Then, on localhost add the following line to your .bashrc: 'alias work="ssh -t remotehost bash --rcfile .bashrc-work"'. Now, whenever you type "work" on localhost you'll ssh into remotehost and automatically find yourself in your special directory. Of course this idea can be adapted to do anything automatically on login.
ssh -X remotehost
Connect to remotehost and tunnel all X traffic over the encrypted connection. To see how this works, run the above command, and then run "xeyes" when you get your shell prompt on the other machine. Notice how it automatically displays on your own X server. I think this should be common knowledge, but it never hurts to give a reminder. Note that if you get an error message like "Gdk-ERROR **: BadWindow (invalid Window parameter) serial 3945 error_code 3 request_code 38 minor_code 0 Gdk-ERROR **: BadAccess (attempt to access private resource denied) serial 3946 error_code 10 request_code 102 minor_code 0" then you should instead use "ssh -Y".
Tunnelling an entire X Session over SSH
Run "ssh -X remotehost" as described above. Now run "gdmXnest &" and then run "export DISPLAY=:20" where "DISPLAY=:20" should be the same thing that gdmXnest just printed. Now run "gnome-session" or "startkde" or whatever you do to run your X Session ("/etc/X11/xdm/Xsession" will do your .xsession file). Note that if you aren't on the same LAN, you'll probably want to use a lightweight window manager.
Email over SSH
I used to do all of my email over a cool but dirty hack. Both incoming and outgoing email go over an SSH Tunnel. Here's some information I wrote up about doing Email over an SSH Tunnel.


(cd /orig/dir; tar cf - .) | (cd /targ/dir; tar xpf -)
Copying with a cp -R will mangle stuff sometimes. If you want to completely copy a tree, this command is the best way to do it. Additional tar options, like --same-owner, will let you keep things even more intact. Another way to do this is: "tar cfC - /orig/dir . |tar xpfC - /targ/dir". They should both do exactly the same thing, though the original example is perhaps a little easier to remember.
tar cf - . |ssh remotehost "cd /targ/dir; tar xf -"
This is logically exactly the same as the tar pipe above, except that this time ssh allows our pipe to cross system boundaries.
find . -type f -name \*.png |tar cvTf - tarfile.tar
Use find to specify exactly which files you want to include in your tar file. This example grabs all png files in the current directory and its subdirectories and throws them into tarfile.tar. You can give very complex criteria (see the man page for find). If tar gets a directory it will tar up everything under it, so make sure to specify "-type f" or at least "! -type d", unless you're actually wanting to include whole subdirectories.


find . [expression] -printf "mail -s subject >%p\n" |bash -s
Find's -exec commands are great but they're limited to what you can do with an exec system call. That means: no pipes, no redirects, no expressions, etc. With this example, you can put absolutely anything that bash understands, including complex loops and expressions, inside the quotes, and Bash will run it as a shell script. Things to remember: %p will be substituted by the filename found (man find for the other dozens of substitutions). Also, you need that trailing '\n' or a semicolon, or bash won't be able to separate your statements. Have fun.


kill -9 `ps -ef |grep something |cut -c 10-15`
Kill everything that matches a regular expression you give it. This is much nicer than typing in numbers manually.
watch "mailq |head -1"
Watch will run a command every few seconds, so you can see when the status of something changes. This example watches the state of the mail queue. When you're waiting for DHCP, "watch ifconfig eth0" is very cool.
du -k |sort -n |tail -30
See which files and directories are using the most space. This is way cooler than a normal du -sk or du -sh.
for old in `ls *.jpg`; do new=`basename $old .jpg`-thumb.jpg; convert -size 200x200 -resize 200x200 $old $new; done
Use ImageMagick to create a bunch of thumbnail images with a maximum width of 200 pixels and a maximum height of 200 pixels (though the ratio will be preserved). It will run on all files *.jpg and will make hello-thumb.jpg from hello.jpg.