I'm on macOS Catalina and I'm trying to move all my "dotfiles" into a folder, where I can place them under version control, then symlink them back into the home folder. I've created a hidden ".dotfiles" folder within the home folder, moved the dotfiles into it, then symlinked them back into the home folder with:

ln -s <dotfile name> ..

However, terminal complains that the commands associated with those dotfiles are no longer found. I'm not sure what exactly I'm doing wrong, but any help would be greatly appreciated.


3 Answers 3


ls -l in upper directory to see what the link points to.

You might find it should be

cd ..
ln -s dotfile_dir/dotfile_name .

Your ln syntax is wrong, which is leading to self-referential symbolic links. For example:

% mkdir .dotfiles
% cd .dotfiles/
% touch .foo
% ln -s .foo ..
% cd ..
% ls -l .foo
lrwxr-xr-x  1 tph  wheel  4 Dec  5 10:38 .foo@ -> .foo

At this point .foo exists but it's a symlink to itself, not to the copy in .dotfiles.

Probably the easiest way to do it is to cd ~ and make the symlinks from there:

% cd ~
% ln -s .dotfiles/.foo .
% ls -l .foo 
lrwxr-xr-x  1 tph  wheel  14 Dec  5 10:46 .foo@ -> .dotfiles/.foo

Assuming the .dotfiles directory was added to $HOME, and you've moved the target dot files into it, then use the following compound command in Terminal:

Hint: Copy and paste the for in do command, no need to type it.

cd .dotfiles
for f in .??*; do [ ! "$f" == ".DS_Store" ] || continue; ln -s "${HOME}/.dotfiles/${f}" "${HOME}/${f}"; done

Then close and reopen Terminal.

This will create a proper working symlink for each dot file in the $HOME/.dotfiles directory into the $HOME directory, because fully qualified pathnames were used.

Note: The use of ?? in .??* is so you do not try making a symlink to . and .. in the .dotfiles directory as they already exist in $HOME and you wouldn't want them symlinked anyway. Without the qualifier you'll get ln: ..//.: File exists and ln: ..//..: File exists. There could also be a .DS_Store file, which you do not want to symlink either, so [ ! "$f" == ".DS_Store" ] || continue; handles it.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .