1

I would like to know if there is any way a file can be moved only if the destination does not exist - in other words, move only if it does not lead to overwriting.

mv --update

seemed first to be the solution, however, if the timestamp of the source path is newer than the destination, move will overwrite it and all attempts to circumvent this by modifying the timestamp before the move will fail.

I need this behaviour to implement a simple file based lock where existence of a 'lock' file indicates that the lock is acquired.

1

3 Answers 3

1

You could use rsync with the --ignore-existing switch:

   skip updating files that exist on receiver

However, I think this is not atomic. You can create advisory locks with flock to make sure the processes you control (Cooperating processes) won't write to it. But another process still could.

The only way you can lock a file without the risk of a another process messing with it is to mount the filesystem with mandatory locking. From <linux_kernel_source>/Documentation/filesystems/mandatory-locking.txt:

What is mandatory locking?

Mandatory locking is kernel enforced file locking, as opposed to the more usual cooperative file locking used to guarantee sequential access to files among processes. File locks are applied using the flock() and fcntl() system calls (and the lockf() library routine which is a wrapper around fcntl().) It is normally a process' responsibility to check for locks on a file it wishes to update, before applying its own lock, updating the file and unlocking it again. The most commonly used example of this (and in the case of sendmail, the most troublesome) is access to a user's mailbox. The mail user agent and the mail transfer agent must guard against updating the mailbox at the same time, and prevent reading the mailbox while it is being updated.

In a perfect world all processes would use and honour a cooperative, or "advisory" locking scheme. However, the world isn't perfect, and there's a lot of poorly written code out there.

1
  • Oh, well for "I need this behaviour to implement a simple file based lock where existence of a 'lock' file indicates that the lock is acquired." which I missed you what Dennis said. Just remember it will be an advisory lock. May 12, 2010 at 13:46
1

If you're on the same filesystem, use link() and unlink() instead of mv:

$ touch src
$ ln src dest && rm src
$ ls
dest
$ touch src2
$ ln src2 dest && rm src2
ln: creating hard link `dest': File exists
$ ls
dest  src2
0

From the open(2) manpage:

Portable programs that want to perform atomic file locking using a lockfile, and need to avoid reliance on NFS support for O_EXCL, can create a unique file on the same file system (e.g., incorporating hostname and PID), and use link(2) to make a link to the lockfile. If link(2) returns 0, the lock is successful. Otherwise, use stat(2) on the unique file to check if its link count has increased to 2, in which case the lock is also successful.

You must log in to answer this question.