Log in / create account | Login with OpenID
DocForge
Programmer's Wiki

Bash

From DocForge

Bash is a popular shell script compatible with the Bourne Shell and POSIX "sh" standards.

Contents

[edit] Starting other programs

The simplest usage for Bash is to start another program. For example, to start vim:

vim

[edit] Rename Files

The Bash shell supports simple for loops. Combined with command line tools, some powerful file editing can be performed.

for fl in *.php;
  do mv $fl $fl.old;
  sed 's/find_string/replace_string/g' $fl.old > $fl;
  rm -f $fl.old; 
done

The semicolon between commands indicates that the first command must complete and return a successful status code before the next comman will execute.

[edit] Activate Subversion Ids

Recursively find all the files in the current directory that have the subversion "Id" keyword but do not have the property set for substitution of this keyword, and set it on those files.

grep -ri '\$Id\$' * | grep -v .svn | grep -v .xml | sed 's/:.*\$//' | xargs svn propset svn:keywords Id

do you see how amazing xargs is yet?

[edit] Delete Dot-Underscore Files

Work in a mixed Mac/Unix/and/or/Windows environment? This is usable as a background cron process to automatically delete dot-underscore files from a directory:

find . -exec sleep 1 \; -name '._*' -exec rm \{\} \;

Find is a rather heavyweight process, so this sleeps for one second between each file it inspects. When it finds a dot-underscore, it deletes it. If this seems to work too slowly, you could also try:

find .-name '._*' -exec rm \{\} \; -exec  sleep 10 \;

...which would sleep for ten seconds only after finding and removing a matching file.

Now, that's all great, but there's something even better if you're having this problem on Mac OS X...

For some reason, when I mount my MacBook Pro's drive as an AppleShare volume on my G5, I still get those dot-underscore files that are only supposed to happen on non-Mac platforms.

But, in this case, we can use Spotlight, leading to the blazingly fast:

mdfind "kMDItemDisplayName == '._*'" | xargs rm

[edit] Always use quotes around your variables

When you use a variable in an if or a while, you should put double quotes around the variable. This will avoid potential problems with spaces. So don't do this:

if [ $foo = "bar" ]; then

but rather do this:

if [ "$foo" = "bar" ]; then

[edit] Use $() instead of backticks for command substitution

The usage of $() has been introduced a while back to replace backticks. So don't do this:

foo=`grep $1 $2`

but do this:

foo=$(grep $1 $2)

For one thing, it makes your code more clear. It also makes nested command substitution easier, e.g.:

foo=`grep $foo \`echo $bar | sed -e 's/backticks/parenthesis/'\``

versus

foo=$(grep $foo $(echo $bar | sed -e 's/backticks/parenthesis/'))

One thing to keep in mind is that the password will show up in the process list with some versions of MySQL, so you may wish to use a my.cnf file as an alternative authentication method.

[edit] Automated Database Backups

Okay, so there are million different ways to backup data, and they're all far more robust than this method. However, sometimes you just need quick and dirty backups, and this will do the trick:

mysqldump -u backup --password=ScydGhondaj0 mydb | gzip -c - > /mnt/backups/sql/db_`date +%Y%m%d_%H%M`.mysql.gz

Or to follow the advice above:

mysqldump -u backup --password=ScydGhondaj0 mydb | gzip -c - > /mnt/backups/sql/db_$(date +%Y%m%d_%H%M).mysql.gz


[edit] Fun with Xargs on Mac OS X

I've got a directory full of eBooks in the godawful Microsoft .lit format. I had marked with the Finder labels the ones I've already read, and wanted to convert all the ones I hadn't read yet into a readable format. The end result was a rather beautiful pipeline, if I do say so myself.

First, I used the mdfind command to filter all the Items that had the red label. We're going to query the kMDItemFSLabel properties; the red label has a value of 6 (I found this out by using mdls on a file with the desired label).

Since I only want to search a particular directory, I use the -onlyin switch to limit the query:

mdfind -onlyin /Users/phil/Desktop/books/ "kMDItemFSLabel != 6"
/Users/phil/Desktop/books/one.lit
/Users/phil/Desktop/books/two.lit
/Users/phil/Desktop/books/other.rtf
/Users/phil/Desktop/books/three.lit
/Users/phil/Desktop/books/something.html
...
...

Some of those aren't .lit files, so I'll just use grep:

mdfind -onlyin /Users/phil/Desktop/books/ "kMDItemFSLabel != 6" | grep ".lit"
/Users/phil/Desktop/books/one.lit
/Users/phil/Desktop/books/two.lit
/Users/phil/Desktop/books/three.lit
...
...

I could have limited the Spotlight query further, but what fun would that be?

Now, ultimately I'm going to use this output with xargs, but because of limitations imposed by the .lit conversion app, I need to get the basename of these files. For this sed will do the trick:

mdfind -onlyin /Users/phil/Desktop/books/ "kMDItemFSLabel != 6" | grep ".lit" | \
    sed 's/\/Users\/phil\/Desktop\/books\///'
one.lit
two.lit
three.lit
...
...

Finally, I pass this onto xargs, the the unfortunately named ConvertLIT tool:

mdfind -onlyin /Users/phil/Desktop/books/ "kMDItemFSLabel != 6" | grep ".lit" | \
    sed 's/\/Users\/phil\/Desktop\/books\///'  | xargs -I \{\} clit \{\} oebps/\{\}/
$ clit one.lit oebps/one.lit/
$ clit two.lit oebps/two.lit/
$ clit three.lit oebps/three.lit/
$ ...
$ ...

I'm replicating the syntax of find's -exec switch with xargs' -I switch. This will replace all occurrences of the {} with the filename from standard input.

Do you have information or insights to contribute to this article? Please feel free to edit this page. Ask questions or contribute to the discussion on this article's talk page.