#!/usr/bin/env sh # this script is compatible with following shells: # dash, ash, bash, zsh note() { printf "%s\n" "$@" } warn() { printf "%s\n" "$@" >&2 } die() { warn "$@" exit 1 } dotless() { local f="$1" local ind="$(expr index "$f" .)" if [ "$ind" -gt 0 ]; then local len="$(expr length "$f")" REPLY="$(expr substr "$f" 2 "$len")" else REPLY="$1" fi #warn "$f -> $REPLY" } backup() { note "backing up $1" mkdir -p "${backup_dir:?backup_dir unset}/$(dirname "$1")" [ -e "$backup_dir/$1" ] && die "backup already exists" mv "$1" "$backup_dir/$1" } hardlink() { if [ -e "$1" ]; then [ "$1" -ef "$2" ] && return [ -h "$1" ] && note "removing symbolic link $1" && rm "$1" if [ -s "$1" ]; then backup "$1" || die "$1 already exists" fi fi ln "$2" "$1" || die "couldn't hardlink $1" } softlink_nix() { if [ -e "$1" ]; then if [ -h "$1" ]; then [ "$(readlink "$1")" = "$2" ] && return note "removing symbolic link $1" rm "$1" else die "$1 already exists and is not a symbolic link" fi fi ln -s "$2" "$1" || die "couldn't symlink $1" } softlink_pseudo() { [ -d "$2" ] || die "$1 is not a directory to softlink" if [ ! -d "$1" ]; then mkdir "$1" || die "couldn't mkdir $1" fi ls -A "$2" | while read -r REPLY; do local d1="$1/$REPLY" local d2="$2/$REPLY" if [ -d "$d2" ]; then if [ "$d1" != ".vim/bundle" ]; then # buggy on Windows #warn $'\e[34m / \e[0m' "$d1 $d2" softlink_pseudo "$d1" "$d2" || exit 1 fi elif [ -f "$d2" ]; then #warn $'\e[34m * \e[0m' "$d1" hardlink "$d1" "$d2" else die "i don't know how to pseudo-symlink $d2" fi done ls -A "$1" | while read -r REPLY; do local d1="$1/$REPLY" local d2="$2/$REPLY" if [ -d "$d2" ]; then : elif [ ! "$d1" -ef "$d2" ]; then [ "$d1" = ".vim/.netrwhist" ] && continue [ "$d1" = ".vim/backup" ] && continue [ "$d1" = ".vim/bundle" ] && continue [ "$d1" = ".vim/swp" ] && continue [ "$d1" = ".vim/undo" ] && continue #warn "new destination file. consider manually moving it:" #warn $'\e[32m + \e[0m' "$d1" warn " + $d1" fi done } softlink() { if [ -n "$MSYSTEM" ]; then # MSYS2 does not have nor emulate symbolic links. softlink_pseudo "$@" || exit 1 else softlink_nix "$@" fi } which readlink >/dev/null || exit 1 # sanity check rc="$(readlink -f "$(dirname "$0")" )" cd "$HOME" backup_dir="$rc/backup-$(date -u '+%s')" for f in .bashrc .zshrc .-shrc .arrays .prezto-compinit .streamcrap .ea \ .vimrc .inputrc .Xresources .screenrc .tmux.conf; do dotless "$f" r="$rc/home/$REPLY" hardlink "$f" "$r" done for d in sh .vim .mpv; do dotless "$d" r="$rc/$REPLY" softlink "$d" "$r" done # ensure that .bashrc gets executed if [ ! -e .bash_profile ] || ! grep -qF .bashrc .bash_profile; then echo >> .bash_profile echo '[[ -f ~/.bashrc ]] && . ~/.bashrc' >> .bash_profile fi is_empty() { local f="${1:?is_empty requires an argument}" find "$f" -type f | while read -r f; do return 1 done || return 1 # just in case pipes mess things up return 0 } # delete any directory structure that may have been included with the OS. # note that i'm careful not to delete them if they contain even a single file, # but you might still want to remove this if you're adapting my install script. for d in Desktop Documents Downloads Music Pictures Public Templates Video Videos; do [ -d "$d" ] || continue is_empty "$d" && rm -r "$d" || note "not removing $d because it contains files" done # create instead my preferred directory structure. mkdir -p opt/local/bin src work play