This Bash trick will make your brain explode

While you can live a (mostly) happy Linux existence with just GUI tools, I think a strong base working on the command-line can drastically improve your flexibility and efficiency. I urge everyone to spend some time studying all of the great Bash tutorials out there.

Terminal Window

I am constantly learning new things. For instance, I had never considered combining multiple commands into a single alias before.

Which leads us to my favorite Bash trick of all time; the single thing I use more than anything else.


Performing actions in a loop over the output of another command.

There are different ways to do this, the most compact being xargs, but I prefer to use while read.

The main reason I like while over xargs is that xargs will die if you're working with too many items since the entire operation happens on a single command-line action whereas while executes many separate actions.

This will make a whole lot more sense with some examples.

Here's one I use all the time:

Deleting all .svn directories from a path (handy for making a working copy not be a working copy any more).

~~~~ {.bash name="code"} find ./ -type d -name ".svn" | while read d; do rm -rf "$d"; done wzxhzdk:0

What you do within the while loop is entirely up to you. All of the usual Bash concepts for stringing commands together (using ;, &, or |) still work.

The real power of this idea is that you can do use it with anything that has newline-separated output.

Let's say you have a file that contains a list of files like this:








Maybe we want to make all files that start with "bar_" world-writable.

~~~~ {.bash name="code"} egrep "^bar_" filelist.txt | while read f; do chmod a+w "$f"; done wzxhzdk:1

Step two does a SELECT on each table and prints all of the ids with an invalid price. Once again, we do a grep to strip out some extra info that mysql is printing out.

~~~~ {.bash name="code"} mysql -B -e "show tables" thedb | egrep -v "^Tables_in_" | while read tbl; do mysql -B -e "SELECT id FROM $tbl WHERE price >= 10000" | egrep "^[0-9]"; done ~~~~

That's the Bash trick I use the most. Remember, it works for anything that has newline-separated output.