Bash script for creating symbolic links

bashfindersymlink

I am relatively new to bash and am having some trouble with a script I am trying to write. After spending the last hour or so researching and trying new techniques, I am still unable to do what I would like.

My goal is this: I have a folder /Volumes/Server\ RAID/Photos where I keep all of my pictures. Each folder is titled YYYY-MM FolderName where there are sometimes spaces in FolderName. Within these folders are three folders: Raw, Edited, and Final. My goal is to, with a single bash script, create symbolic links on my Desktop for each Final folder AND rename it to its parent folder. Example: I would like /Volumes/Server\ RAID/Photos/2016-10\ Fleet\ Week/Final to have a symbolic link on the Desktop named 2016-10 Fleet Week.

I have tried many different varieties of the code I have posted down below, but the code I have included was the most concise code (although it didn't work).

Code description:

  1. cd to Desktop so that symlinks are created there
  2. use for loop to loop through folders
  3. create symlink – here is the problem: I need to include the folder name in the file path somehow, but also add \ before the spaces so that the command doesn't fail. HOWEVER, I have been getting error messages saying that there is no place called RAID/Photos which makes me think the script is stumbling on the first space, even with the backslash.
  4. Change name of Final symlink to the folder name. (I assumed I didn't need full directories here because I'm already in Desktop

    cd Desktop
    for f in /Volumes/Server\ RAID/Photos;
    do ln -s /Volumes/Server\ RAID/Photos/"$f"/Final
    mv Final $f
    done
    

QUESTION: Can someone please help me flush out this script? (I am mainly concerned with part three, but I wouldn't say no to help with the rest of it, either).

Best Answer

When running into troubles with shell quoting, it always help to add echo statements in suitable places in your script to see what's going on.

Let's look at this line by line:

for f in /Volumes/Server\ RAID/Photos;

This only runs once, and sets f to Volumes/Server RAID/Photos, which probably isn't what you want.

do ln -s /Volumes/Server\ RAID/Photos/"$f"/Final

f is set to the full path (see above), so this expands to

ln -s /Volumes/Server\ RAID/Photos//Volumes/Server\ RAID/Photos/Final

which (again) is not what you want to see here.

mv Final $f

See above :-)

There are various ways to tackle this, but in your case I would to something like the following (to get around the challenge of having to extract the directory name from the source path)

cd /Volumes/Server\ RAID/Photos/
for f in *; do
    if [ -d "$f" ]; then 
        if [ -d "$f"/Final ]; then
            ln -s "/Volumes/Server RAID/Photos/$f/Final" ~/Desktop/"$f"
        fi
    fi
done

The two ifs cover the cases where there are files in the source directory or the Final directory is missing.