I learned that in some circumstances bash will exit with exit status 0 after a syntax error in your script. I.e. when trap ERR is defined. That is so totally uncool.
Monthly Archives: January 2012
Creating a temp file in bash
To create a new temporary file in bash use the mktemp command. E.g.:
path="$(mktemp)"
There’s a -d argument to mktemp that will make a temp directory.
Replacing new lines with nulls in bash
If you have a list of file names separated by new lines, and you want to turn it into a list of file names separated by null characters, for instance for use as input to xargs, then you can use the tr command, like this:
$ cat /path/to/new-lines | tr '\n' '\0' > /path/to/null-separated
I found a whole article on various ways to replace text on *nix: rmnl — remove new line characters with tr, awk, perl, sed or c/c++.
Extracting a single file from a tar archive
You can use a parameter to the -x command line switch to tell the tar command that you just want to extract one particular file from the archive. For example:
$ tar -x filename/to/extract -f tarfile.tar
You can use the -O command line switch in conjunction with the above to have the file’s contents printed on stdout rather than created in the file system.
Bash subshells
I read Chapter 21. Subshells of The Linux Documentation Project‘s Advanced Bash-Scripting Guide. One fun trick I learned was using a subshell to test if a variable is set:
if (set -u; : $variable) 2> /dev/null then echo "Variable is set." fi
Changing parent’s directory from a subshell
I was trying to figure out how to have a child process change the current directory of a parent process. Turns out you can’t quite do that. One thing I guess you could do is export a global variable and then have the parent check that when the child returns, but I decided on another approach. What I do is write a file to ~/bin/errdir that contains a single line in the format:
pushd "/path/to/directory"
I can then source this as a command file after my script has run to change directory into the directory where the last erroneous file was encountered with the command:
$ . errdir
When I’m finished I can just type ‘popd’ to return myself to wherever I was before I changed into the error directory.
Error handling in bash
I’ve been learning about approaches to error handling in bash. I found Error handling in BASH, Exit Shell Script Based on Process Exit Code, Writing Robust Bash Shell Scripts and Bash: Error handling all of which contained a nugget of useful information.
Particularly I learned about $LINENO, set -e (equiv: set -o errexit), set -o pipefail, set -E, set -u (equiv: set -o nounset), set -C (equiv: set -o noclobber), #!/bin/bash -eEu, trap, shopt -s expand_aliases, alias, $PIPESTATUS, subshells, unset, and more.
If you call exit without specifying a return code then $? is used, I didn’t know that.
I found this code snippet that demos a relatively race-condition free method of acquiring a lock file:
if ( set -o noclobber; echo "$$" > "$lockfile") 2> /dev/null; then trap 'rm -f "$lockfile"; exit $?' INT TERM EXIT critical-section rm -f "$lockfile" trap - INT TERM EXIT else echo "Failed to acquire lockfile: $lockfile." echo "Held by $(cat $lockfile)" fi
Setting modification time on files in Linux
If you want to change the modification time of a file on Linux, the command you’re looking for is touch. You can use touch with the -r parameter to specify a reference file who’s date and time information will be used as the basis for a new (or existing) file.
Unix command to format a number of bytes as a human readable value
It took me a while, but I finally figured out how to print a number from a bash script properly formatted with commas as thousand’s separators. For those like me who weren’t in the know, the magical incantation is:
printf "%'d" 123456
That will format 123456 as 123,456. Much easier to read when you’re dealing with large numbers such as the sizes of files in gigabytes.
So now if I could only find the Unix command that took a number of bytes and turned it into an approximate value with GB or MB suffixes.
Yo man you are Basic
I’ve been restoring my archives — 10,000,000 files from the past 13 years — and while I did so I had a little bit of a trip down memory lane. I found some old Visual Basic 6 database programs that I wrote when I was in high school, including a phone book, a diary, a time sheeting system, and a few other miscellaneous tools. In order to get them to run I had to get my compiler out to fix a few data object dependencies (DAO5) and a few hardcoded configuration settings such as the paths to database files. So I reinstalled my old VB6 development environment, which I’m pleased to say still works (although I’m still running Windows XP). Good fun. :)