2

I have a directory and a symlink to it:

mkdir dir
ln -s dir dir_symlink

I want to replace the symlink with the directory and the directory with the symlink. Is there a way to do that atomically (or very fast)? The directory is large.

dir should now be a symlink to the dir_symlink directory (which is no longer a symlink, and contains the former contents of dir).

  • On any modern filesystem, a renaming is fast as it does not depend on the content / size of the directory / file. – xhienne Aug 3 '17 at 22:52
  • It isn't possible to do it atomically with user-level tools alone. (It's possible to do it “very fast” with three mv commands, of course.) It might be possible with a union mount. – Gilles Aug 3 '17 at 23:12
2

if I had to do this very often, I would write a little bash script like this:

#!/bin/bash

echo "select symlink"
read -e -r symlink
echo "select directory"
read -e -r dir

var=$(echo "$dir" | sed 's/\///g')

rm "$symlink"
mv "$dir" "$symlink"
ln -s "$symlink" "$var"

the sed command removes the / that gets added when you use auto-complete for the input.
Note: it would remove all of them, also if you selected a directory tree.

You could tell sed to only match the end of line like this: sed 's/\/*$//g'

  • bash (and ksh and zsh) can remove a trailing slash (and only a trailing one) with ${dir%/} – dave_thompson_085 Aug 4 '17 at 4:36
  • thanks for this one @dave_thompson_085, should I update my answer? – nath Aug 4 '17 at 18:08
2

If the directories are on same filesystem mv is only renaming the directory and doesn't involve any copying. Just remove the old symlink, rename the directory using mv and create a new symlink.

  • 2
    This is not atomic, but it's the best you can do. – Celada Aug 3 '17 at 22:37
  • Updated the answer. On same filesystem, mv should be atomic as far as I know. – sebasth Aug 3 '17 at 22:45
  • 1
    There are two operations involved: mv + ln. They can't be both done atomically – xhienne Aug 3 '17 at 22:50
  • Of course, I don't think I have claimed such. – sebasth Aug 3 '17 at 22:50
2

It's worth noting that if this is on a macOS machine, the new APFS filesystem supports atomic swaps for just this type of scenario. Although the functionality doesn't seem to be built into a command such as mv, it is accessible with a little bit of Swift code (the C code is almost identical, but you can easily just paste this into the Swift REPL, which is easier):

import Foundation
renamex_np("/path/to/file/one", "/path/to/file/two", UInt32(RENAME_SWAP))

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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