There are a few ways to interpret the operation of "replacing one file with another", but the one I want to focus on here is the one that can be achieved with the command
mv /that/there/someotherfile /this/here/somefile
In this example /that/there/someotherfile
and /this/here/somefile
are supposed to be regular files currently existing in the filesystem.
If all goes well, after running the command above, the file "formerly known as" /that/there/someotherfile
will have disappeared, but its content will now be the new content of the file /this/here/somefile
. The latter's former content will have been "overwritten."
Now consider the analogous operation of "replacing one directory with another." E.g. overwriting some directory /path/to/targetdir
with the directory /some/other/path/to/sourcedir
. I can do this with
rm -rf /path/to/targetdir && mv /some/other/path/to/sourcedir /path/to/targetdir
Can I do this with a single "more-or-less standard"1 command that works irrespective of the contents of the two directories in question?
I know that, if /path/to/targetdir
happeans to be an empty directory, then
mv -T /some/other/path/to/sourcedir /path/to/targetdir
...will do the job.
Also, I know that if /path/to/targetdir
does not contain any relative paths that is not also present under /some/other/path/to/sourcedir
, and all relative paths present under both directories point to file system items of the same type (i.e. they are both directories, or both regular files, etc.), then the following gets close to the operation described above
rsync -a --remove-source-files /some/other/path/to/sourcedir/ /path/to/targetdir
Of course, it would not be difficult to implement2 a script or a function to encapsulate the rm -rf
+ mv
sequence given above, but I would like to avoid implementing something that is already available through more-or-less standard Unix commands.
1 I realize that the answer to this question depends critically on what one considers the set of permissible commands, and, unfortunately, here I can offer nothing better than vigorous hand-waving... For example, I regard cp
and mv
as "more-or-less standard", but even in this case, some of the options these commands take may not be. In fact, if one makes this condition sufficiently precise (e.g. limiting the permissible commands to the "mandatory POSIX untilies"), there may be no general way to "replace one directory with another", in the sense described above, using a single command. If so, feel free to define the set of permissible commands in a way that you find would render your sufficiently useful and/or interesting. In other words, on the choice of the set of permissible commands, I am ready to defer to your good taste.
2 Famous last words.
mv
, or create abash
function. Why hasn't it been implemented yet? It's too scary and easy to fail spectacularly in many unpredicable ways. – Artem S. Tashkinov Jan 21 '22 at 13:20mv somefile otherfile
doesn't just make the content ofsomefile
appear inotherfile
; it's actually the same file with a new name. The rename will keep the inode number and permissions etc. intact.cp somefile otherfile && rm -f somefile
would be different in that regard. – ilkkachu Jan 21 '22 at 13:58rm -rf target && mv source target
? I.e. why does it matter if it's two commands or one? If you're concerned about the move being atomic, you'd need a system call that can replace the directory atomically, and you can't do that to a non-empty directory with plainrename()
as you noted. Linux'srenameat2()
looks to have theRENAME_EXCHANGE
flag which looks like it could work, though. – ilkkachu Jan 21 '22 at 14:02rm target && mv source target
is that for a very brief interval,target
does not exist. I think that is what OP is trying to avoid/mitigate. – DopeGhoti Jan 21 '22 at 14:24