Unexpected behavior of bash script used to sync dotfiles I'm using essentially this script for keeping my dotfiles under version control. I recently added a snippets folder inside my emacs.d directory and listed it as one of the things that should be symlinked to from my home directory. However, when I run the script now it creates a symlink to snippets inside snippets itself. 

Here's the relevant bit of the script: 

#!/bin/bash
############################
# .make.sh
# This script creates symlinks from the home directory to any desired dotfiles in ~/dotfiles
############################

########## Variables

dir=~/.dotfiles                    # dotfiles directory
olddir=~/.dotfiles_old             # old dotfiles backup directory
files="bash_profile gitignore gitconfig zshrc jrnl_config emacs.d/init.el emacs.d/custom.el emacs.d/snippets scripts/makeadate.js config/karabiner/assets/complex_modifications config/karabiner/karabiner.json"    # list of files/folders to symlink in homedir
##########

# create dotfiles_old in homedir
echo -n "Creating $olddir for backup of any existing dotfiles in ~ ..."
mkdir -p $olddir
echo "done"

# change to the dotfiles directory
echo -n "Changing to the $dir directory ..."
cd $dir
echo "done"

# move any existing dotfiles in homedir to dotfiles_old directory, then create symlinks from the homedir to any files in the ~/dotfiles directory specified in $files
for file in $files; do
    echo "Moving any existing dotfiles from ~ to $olddir"
    mv ~/.$file $olddir
    echo "Creating symlink to $file in home directory."
    ln -s $dir/$file ~/.$file
done


So, before running the script, ~/.dotfiles/emacs.d/snippets contains only two subdirectories, latex-mode and mhtml-mode. After running the script, it contains a new symlink to ~/.dotfiles/emacs.d/snippets. I suspect the problem has something to do with the fact that one of the values that the variable $file is taking is a directory. But I don't know exactly what the problem is.
If target is an already existing directory, then the command ln -s source target will create a link target/source in that directory, pointing to the original source. That's what's going on here: the directory .emacs.d/snippets/ exists at the start, and you're running the command

ln ~/.dotfiles/.emacs.d/snippets ~/.emacs.d/snippets


which creates a link in the existing snippets to the other snippets.

You could do ln -s ~/.dotfiles/.emacs.d/snippets/* ~/.emacs.d/snippets instead. Or delete everything in .emacs.d and do ln -s ~/.dotfiles/.emacs.d/* ~/.emacs.d. (Obviously make copies first in case something goes wrong.) Or perhaps even delete .emacs.d and create a new version which is just a symlink.