Tag: bash

Adding defensive sanity checks

I recently needed to make a set of several favicons, so I went to the web to see if anyone had a script I could borrow steal.

Sure enough, I found one written by Joshua McGee: “Create a favicon with ImageMagick” (not reproduced here for copyright reasons).

It was a simple enough script, just a series of escaped commands. I noticed, however, that it assumed a few things:

  • An image file was specified on the command line,
  • The image existed, and
  • Imagemagik was installed.

In other words, the script was not developed defensively. This makes sense: it was just a bang-out.

The script had no inline documentation, and if a favicon file that already existed in the current directory would be silently overwritten—not good.

I’m clumsy: I delete and overwrite files all the time, so I could use a little help. Maybe I can tidy up the script? (more…)

Bulk process RAW image files

Recently I had to convert about 250 RAW image files to PNGs. For neatness, I wanted to convert the upper-case filenames the camera assigned with a lower-case name.

A little bash script-fu is all it took:

clean_pics.sh

#!/bin/bash
# Extract from SD Card
for i in /Volumes/SDCARD/DCIM/100ND40X/DSC_0*; do
 filename=$(basename "$i")
 lower_file="$(echo $filename | tr '[A-Z]' '[a-z]')"
 # verify it doesn't already exist
 newfile="${lower_file%.*}.png"
 echo -e "Processingnt$i tont$newfile"
 if [[ -e $newfile ]]; then
  echo "****SKIPPING"
 else
  convert "$i" "$newfile"
 fi
done

echo -e "Detoxing..."
find . -iname "*.png" -exec detox "{}" ;

echo "Procedure complete."

(“SDCARD”, etc is the path to the source files)

Once the script was up and running, it took about 1/2 hour to process all the files. Meanwhile, I was off doing something else!

How to prevent duplicate directories in your path

Forest Path image
What happens with the Path

The path is set via a myriad of config files. It is very easy to accidentally add the same directory to the path, and there is no built-in mechanism to bash/zsh from preventing this situation.

While duplicate entries generally have no impact on performance, they do make reading and editing the path more difficult. If you need to remove a directory from the path, you may miss removing the duplicate(s), resulting in unexpected behavior.

Easy Fix

The easiest fix is prevention, which can be accomplished by using a function to add directories to the path.

Throughout your shell’s configuration files, you may see things like:

export PATH=/fizz/buzz:$PATH

This line appends /fizz/buzz to the PATH, which is separated from the other directories by a colon (:). The $PATH is the variable of the existing path.

Finally, the export command ensures the PATH variable changes are available after the configuration file finishes executing.

Directory-Adding Function

Edit your /etc/bashrc to make the function available to all accounts on your machine, or ~/.bashrc to make it available only for your account. Add this function:

pathmunge () {
  if ! [[ $PATH =~ (^|:)$1($|:) ]] ; then
    if [ "$2" = "after" ] ; then
      PATH=$PATH:$1
    else
      PATH=$1:$PATH
    fi
  fi
}

Now you can call this function wherever you need to add a directory to the path and it will add it only if it doesn’t already exist on the path. There are two ways to do this, depending upon where you want to add the directory.

Insert at the beginning of the path

To add a directory to the beginning of the path (directories are searched in the order they appear in the path):

pathmunge /path/to/dir

Append to the end of the path

To add a directory to the end of the path, you add the after keyword:

pathmunge /path/to/dir after

Cleanup

Go through your configuration files and update every line that adds directories to the path to use  pathmunge instead.

⚠️ Caveat: only add one directory at a time, otherwise you may end up with duplicates.

export PATH=/foo/bar:/fizz/buzz:$PATH

❌ Don’t:

pathmunge /foo/bar:/fizz/buzz

✅ Do:

pathmunge /foo/bar
pathmunge /fizz/buzz

Note: other shells use other files; be sure you know what you’re doing before you go around mucking with these, especially the files in the /etc directory!

Technique credit: Sam Halicke and Christopher Cashell at Serverfault.

Updated 2025.02.13 – cleaned up and made some minor corrections.