4

My bash script makes copies of some files to some multiple directories.

In order to save space and maximize speed, I would prefer to make hardlinks instead of copies, since all copies need to remain identical during their life anyway.

The script is ran in different computers, though, and there may be the case where the destination directory exists in a different volume to the origin's. In such a case, I cannot make a hardlink and need to just copy the file.

How do I check if origin and destination directory exist in the same volume, so that I either hard link or copy depending on it?

elmimmo
  • 442
  • 2
  • 11

2 Answers2

4

A simple way to do so, is just to try both:

    ln "$FROM" "$TO" || cp "$FROM" "$TO"

Depending upon your purposes, creating a reference copy (which is almost as lightweight as an hardlinked file, but allows the two copies to be edited/diverge in future) might work:

    cp --reflink=auto "$FROM" "$TO"

But, you can obtain the device filesystem's device ID using stat:

    if [ $(stat -c %D "$FROM") = $(stat -c %D "$TARGET_DIR") ]; then
          ln "$FROM" "$TARGET_DIR"/
    else
          cp "$FROM" "$TARGET_DIR"/
    fi
BRPocock
  • 13,638
  • 3
  • 31
  • 50
  • The 1st option seems to be the best (albeit the error message when ln fails is a bit nasty). The two other solutions have cross-plattorm issues (I tried them on Mac OS X, which does not seem to support reflinks and its `stat` command (taken from BSD apparently) does not accept the `-c` parameter either). – elmimmo Jan 15 '12 at 22:51
1

The easy way, by checking whether ln fails where cp succeeds:

ln $SRC $TARGET || cp $SRC $TARGET
thiton
  • 35,651
  • 4
  • 70
  • 100
  • wouldn't cp -l just fail cross-device? Also, since hardlinking preserves 'all' metadata, I suggest `cp -al` (or `cp -a` in the first variant) – sehe Jan 11 '12 at 16:05
  • @sehe: The `cp -l` failing was my second thought, tried it, it fails. So, no good alternative, thanks for the hint. – thiton Jan 11 '12 at 16:07