3
\$\begingroup\$

Right now I am working on an install and uninstall script for my vim configuration files. The install script links files and directories and the uninstall script deletes those links. I just want to make sure that this code is somewhat safe, are there better ways of doing the same thing? Here is the code I have right now:

Install Script:

#!/bin/bash
# The install script for my vim dotfiles.
# Find the location of the script.
SCRIPT_DIRECTORY="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

# The source directory and target directories.
SOURCE_LOCATION="$SCRIPT_DIRECTORY/src" # Contains the files and directories I want to work with.
TARGET_LOCATION="$SCRIPT_DIRECTORY/test-home" # The location I want to link to, in production this would be "~/"

# Link the files from source to the target with a dot appended to the front.
find $SOURCE_LOCATION -mindepth 1 -maxdepth 1 -printf "%P\n" | while read file; do
    echo "Linking $SOURCE_LOCATION/$file to $TARGET_LOCATION/.$file"
    ln -s "$SOURCE_LOCATION/$file" "$TARGET_LOCATION/.$file"
done

Uninstall Script:

#!/bin/bash
# The uninstall script for my vim dotfiles.
# Find the location of the script.
SCRIPT_DIRECTORY="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

# The source directory and target directories.
SOURCE_LOCATION="$SCRIPT_DIRECTORY/src" # Contains the files and directories I want to work with.
TARGET_LOCATION="$SCRIPT_DIRECTORY/test-home" # The location I want to link to, in production this would be "~/"

# Remove the links the install script would create.
find $SOURCE_LOCATION -mindepth 1 -maxdepth 1 -printf "%P\n" | while read file; do
    echo "Removing $TARGET_LOCATION/.$file"
    rm -I "$TARGET_LOCATION/.$file"
done
\$\endgroup\$
4
\$\begingroup\$

If you're worried about it being safe, probably verifying that what you're deleting is a symlink and bailing out if not would be a good start:

if [[ ! -h $TARGET_LOCATION/.$file ]]; then
    printf >&2 "%s is not a symlink!\n" "$TARGET_LOCATION/.$file"
    return 1
fi

Also, your deploy script doesn't seem to much care if there are existing .vim/.vimrc files to deal with, so I have to wonder: why bother juggling the configs? If there's any possibility someone else's config will be there, best check for it

if [ -e "$TARGET_LOCATION/.$file" ]; then
    printf >&2 "%s exists, cowardly refusing to clobber it\n" "$TARGET_LOCATION/.$file"
    return 1
fi

You might also consider placing this at the top of your script:

set -e

This will cause your script to cease execution immediately if any command in the pipe returns a non-0 status and isn't caught by an explicit check (if/then, &&/||, etc -- see manpage for the gory details). Generally, I recommend to always write shell with this on, but especially so if you're doing something you're nervous will misbehave.

I am not sure about this:

SCRIPT_DIRECTORY="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

Is that how you are getting an absolute path? I would be cautious, if for some reason that command fails, even set -e won't catch it (launched in a subshell), then you have an unset $SCRIPT_DIRECTORY. That may cause find to fail, but it might cause it to walk your CWD, too.. hard to tell at a glance. I personally use a set of functions I tote around that do path normalization and has proper abspath() function to use, but in the interest of keeping this simple, consider skipping the clever tricks and set an explicit path (assuming it's not going to be changing). If that's not an option, I would add a sanity check to make sure what I'm walking and copying is what I expect. This can be as simple as checking a file is there that wouldn't be in ~ already.

And just throwing this out there: Consider making your dotfiles permanent but with a different name, then use an alias/function to set the desired config, e.g.: myvim () { vim -u "$HOME/.my.vimrc" "$@"; }. Not sure of your situation, but it might be more pleasant/less sketchy way to handle it.

\$\endgroup\$
  • \$\begingroup\$ Brilliant answer, that's just the advice I was looking for! \$\endgroup\$ – Devin M Mar 25 '12 at 22:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.