I carry all of my music around on a 1TB USB drive and have a udev rule to symlink it to $HOME/Music/ when I plug it in to one of my laptops, which it does.

The issue I have is that this works fine where the directory does not exist on the laptop, but it doesn't create the requisite tree where there is a pre-existing directory of the same name (Artist/Album/*.flac) on the laptop.

The script I currently run is this one:

#!/usr/bin/env bash
# repopulate music links when drive plugged in

shopt -s nullglob
export DISPLAY=:0
export XAUTHORITY=/home/jason/.Xauthority

music=(/media/Apollo/Music/*)

find /home/jason/Music -type l -exec rm {} \;
for dirs in "${music[@]}"; do
  ln -s "$dirs" /home/jason/Music/ 2>/dev/null
done
status1=$?

mpc update &>/dev/null

status2=$?
if [[ "$status1" -eq 0 && "$status2" -eq 0 ]]; then
  printf "%s\n" "Music directory updated" | dzen2 -p 3
fi

How can I ensure that where a directory exisits on both the laptop and the USB drive, but the contents are slightly different, the files are correctly symlinked? For example:

USB drive:

Music -- Matthew Shipp -- Patoral Composure -- Track 1
                                            -- Track 2 etc...
                       -- Strata            -- Track 1
                                            -- Track 2 etc...
                       -- Equilibrium       -- Track 1
                                            -- Track 2 etc...

Laptop:

Music -- Matthew Shipp -- Patoral Composure -- Track 1
                                            -- Track 2 etc...

In this case, no symlinks to the albums Strata or Equilibrium will be created, presumably because the parent directory (Matthew Shipp) exists.

I would prefer not to use rsync to copy the actual data across as I have limited space on the laptops and with mpd able to follow symlinks, I have no need to copy the files across.

Is it possible to tweak my script to propagate symlinks into pre-exisiting directories on the laptop?

  • 1
    Care to use union mounts, for example via overlayfs? – muru Jan 16 '15 at 5:26
  • @muru I had not considered it. If you think it would fulfill my use case, please write up an answer. – jasonwryan Jan 16 '15 at 5:30
up vote 8 down vote accepted
+200

Since your primary aim is to have a combined view of your local and external Music folder, I think a union mount via overlayfs could be used, especially if the files are not being written to.

The basic command is, in older kernel versions (<3.18):

mount -t overlayfs -o lowerdir=/read/only/directory,upperdir=/writeable/directory overlayfs /mount/point

For example:

$ ls Documents
374620-63301.pdf        My Kindle Content   scan0005.jpg
BPMN2_0_Poster_EN.pdf   scan0003.jpg        StrongDC++
$ ls devel
cse           ossec     ubuntu-14.04-desktop-amd64-ssh.iso
nexus         scripts   zsh-syntax-highlighting
$ sudo mount -t overlayfs -o lowerdir=$PWD/Documents,upperdir=$PWD/devel overlayfs ~/Documents
$ ls Documents
374620-63301.pdf        scan0003.jpg           
BPMN2_0_Poster_EN.pdf   scan0005.jpg    
cse                     scripts
My Kindle Content       StrongDC++
nexus                   ubuntu-14.04-desktop-amd64-ssh.iso
ossec                   zsh-syntax-highlighting

One drawback is the need for sudo, which can perhaps be taken care of using a careful NOPASSWD rule.


In light of Jason's blog post, the mount command for newer kernels changes to using overlay as the filesystem, instead of overlayfs, and using an additional workdir. The kernel documentation now codifies this:

At mount time, the two directories given as mount options "lowerdir" and "upperdir" are combined into a merged directory:

mount -t overlay overlay -olowerdir=/lower,upperdir=/upper,\
  workdir=/work /merged

The "workdir" needs to be an empty directory on the same filesystem as upperdir.

  • That worked great: with a few caveats. On Arch Linux, the module and filesystem is just called overlay and it also requires workdir to be specified (on the same filesystem as upperdir). I won't accept this yet as I'd like to see if there are other solutions. Thank you, though. – jasonwryan Jan 16 '15 at 6:45
  • @jasonwryan Possibly the effect a newer kernel? I tested this out on Ubuntu 14.04. – muru Jan 16 '15 at 6:50
  • Yes: this is on 3.18.2-2. – jasonwryan Jan 16 '15 at 6:54
  • any insight into why it's necessary to specify workdir in more recent kernels? the kernel docs only say The "workdir" needs to be an empty directory on the same filesystem as upperdir. there's no mention of what workdir is for or why it's necessary to provide it. – jayhendren Apr 15 '15 at 0:03
  • @jayhendren From the post that added this option: "Work directory is used to prepare files before atomically swithing with destination and needs to be on the same filesystem as upperdir." – muru Apr 19 '15 at 13:27

You can also use gnu stow, a symlink farm manager.

Assume the following layout:

.
├── drive
│   ├── a
│   │   ├── b
│   │   │   └── bar
│   │   └── c
│   │       └── baz
│   └── b
└── music
    └── a
        └── b
            └── foo

Execute: $ stow --target music --dir drive .

Result:

.
├── drive
│   ├── a
│   │   ├── b
│   │   │   └── bar
│   │   └── c
│   │       └── baz
│   └── b
└── music
    ├── a
    │   ├── b
    │   │   ├── bar -> ../../../drive/a/b/bar
    │   │   └── foo
    │   └── c -> ../../drive/a/c
    └── b -> ../drive/b
  • Thanks: that is something I had not considered. – jasonwryan Jan 18 '15 at 21:28

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.