1

I'm trying to modify thoughtbot's bash script to symlink dotfiles into the home directory, but I want to store my files in a subdirectory.

The original from the thoughtbot script is:

#!/bin/sh

for name in *; do
  target="$HOME/.$name"
  if [ -e "$target" ]; then
    if [ ! -L "$target" ]; then
      echo "WARNING: $target exists but is not a symlink."
    fi
  else
    echo "Creating $target"
    ln -s "$PWD/$name" "$target"
  fi
done

My dotfiles are in a subdirectory called files. I tried changing the for loop to:

for name in files/*, for name in ./files/*, for name in 'files/*', etc, but none of that worked.

After a bit of research, I see that you can loop through files in subdirectories using find like so:

find ./files -type f -exec "do stuff here"  \;

And I see that I can get reference to each file with '{}', but I don't understand how I can operate on the file and make a symlink.

I tried:

find ./files -type f -exec "ln -s '{}' $HOME/'{}'"  \;

but that doesn't work because '{}' is the relative path of the file from the parent directory, not just the name of the file.

What's the correct way to do this?

For reference, this is what my directory structure looks like:

https://github.com/mehulkar/dotfiles

1
  • Use -execdir instead of -exec; the former executes the command in the directory that contains the respective file instead of the directory you're currently in. (i.e., {} will only contain the name of the file, not its full path relative to your CWD) Commented Oct 24, 2013 at 21:25

2 Answers 2

1

Your original script isn't working for dotfiles because you need to say:

shopt -s dotglob

Saying

for file in *

wouldn't match filenames starting with dot by default.

Sign up to request clarification or add additional context in comments.

3 Comments

This worked great. I also found this answer to loop through the results of find files -type f. How do I slice off the files/ part of the output now?
@MehulKar You can use basename. Saying filename=$(basename "$name") would store the filename without the directory name, i.e. the files/ part, into the variable filename.
Thanks, I ended up using string manipulation, but basename works too.
0

... but that doesn't work because '{}' is the relative path of the file from the parent directory, not just the name of the file.

Try

find `pwd`/files -type f -exec "ln -s '{}' $HOME/'{}'"  \;

or

find $(pwd)/files -type f -exec "ln -s '{}' $HOME/'{}'"  \;

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.