Portable, race-free equivalent of mv -T DIR1 DIR2?
It seems mv -T
is a GNU extension to mv
.
Is there a robust way (race-free, portable, and otherwise without "gotchas") to do the equivalent of mv -T dir1 dir2
?
To be clear:
I DO NOT want this to ever result in
dir2/dir1
.
Ifdir2
exists, I want the command to fail. Ifdir1
is moved at all, it must becomedir2
.I DO NOT want to move out every child one-by-one. I want to move the directory itself.
I DO want to avoid race conditions. It's trivial to test if
dir2
exists first, but then it might be created after the check but before the move.
filesystems mv posix
|
show 3 more comments
It seems mv -T
is a GNU extension to mv
.
Is there a robust way (race-free, portable, and otherwise without "gotchas") to do the equivalent of mv -T dir1 dir2
?
To be clear:
I DO NOT want this to ever result in
dir2/dir1
.
Ifdir2
exists, I want the command to fail. Ifdir1
is moved at all, it must becomedir2
.I DO NOT want to move out every child one-by-one. I want to move the directory itself.
I DO want to avoid race conditions. It's trivial to test if
dir2
exists first, but then it might be created after the check but before the move.
filesystems mv posix
I don't think it's possible to satisfy "Ifdir2
exists, I want the command to fail" portably; POSIX requiresrename
to delete an empty dir2 and succeed.
– Michael Homer
2 hours ago
The spec text: "If the old argument points to the pathname of a directory, the new argument shall not point to the pathname of a file that is not a directory. If the directory named by the new argument exists, it shall be removed and old renamed to new. [...] If new names an existing directory, it shall be required to be an empty directory.". That also applies torenameat
. I don't believe there can be any portable method to rename a file that does not go through that path. Given that, which of your requirements can you relax? What sorts of race condition are you concerned with?
– Michael Homer
2 hours ago
Related: mv: Move file only if destination does not exist
– Freddy
2 hours ago
@MichaelHomer: Interesting, thanks. The race condition I'm trying to avoid isdir1
landing insidedir2
, which can happen if multiple processes try to run this command at once. However, I guess it would be fine if an emptydir2
were deleted. Would that help? Also, if there's still no single POSIX solution, I'd be interested in knowing if there are even platform-specific solution that I can call. E.g. is there a solution that works on Mac, let alone other platforms? I haven't found any.
– Mehrdad
2 hours ago
Therenameat2
system call takes a flag argument and one such flag isRENAME_NOREPLACE
which causes it to: "Don't overwrite newpath of the rename. Return an error if newpath already exists." ... But that doesn't really satisfy "portable", so not sure it solves your problem...
– filbranden
1 hour ago
|
show 3 more comments
It seems mv -T
is a GNU extension to mv
.
Is there a robust way (race-free, portable, and otherwise without "gotchas") to do the equivalent of mv -T dir1 dir2
?
To be clear:
I DO NOT want this to ever result in
dir2/dir1
.
Ifdir2
exists, I want the command to fail. Ifdir1
is moved at all, it must becomedir2
.I DO NOT want to move out every child one-by-one. I want to move the directory itself.
I DO want to avoid race conditions. It's trivial to test if
dir2
exists first, but then it might be created after the check but before the move.
filesystems mv posix
It seems mv -T
is a GNU extension to mv
.
Is there a robust way (race-free, portable, and otherwise without "gotchas") to do the equivalent of mv -T dir1 dir2
?
To be clear:
I DO NOT want this to ever result in
dir2/dir1
.
Ifdir2
exists, I want the command to fail. Ifdir1
is moved at all, it must becomedir2
.I DO NOT want to move out every child one-by-one. I want to move the directory itself.
I DO want to avoid race conditions. It's trivial to test if
dir2
exists first, but then it might be created after the check but before the move.
filesystems mv posix
filesystems mv posix
asked 2 hours ago
MehrdadMehrdad
1,18141432
1,18141432
I don't think it's possible to satisfy "Ifdir2
exists, I want the command to fail" portably; POSIX requiresrename
to delete an empty dir2 and succeed.
– Michael Homer
2 hours ago
The spec text: "If the old argument points to the pathname of a directory, the new argument shall not point to the pathname of a file that is not a directory. If the directory named by the new argument exists, it shall be removed and old renamed to new. [...] If new names an existing directory, it shall be required to be an empty directory.". That also applies torenameat
. I don't believe there can be any portable method to rename a file that does not go through that path. Given that, which of your requirements can you relax? What sorts of race condition are you concerned with?
– Michael Homer
2 hours ago
Related: mv: Move file only if destination does not exist
– Freddy
2 hours ago
@MichaelHomer: Interesting, thanks. The race condition I'm trying to avoid isdir1
landing insidedir2
, which can happen if multiple processes try to run this command at once. However, I guess it would be fine if an emptydir2
were deleted. Would that help? Also, if there's still no single POSIX solution, I'd be interested in knowing if there are even platform-specific solution that I can call. E.g. is there a solution that works on Mac, let alone other platforms? I haven't found any.
– Mehrdad
2 hours ago
Therenameat2
system call takes a flag argument and one such flag isRENAME_NOREPLACE
which causes it to: "Don't overwrite newpath of the rename. Return an error if newpath already exists." ... But that doesn't really satisfy "portable", so not sure it solves your problem...
– filbranden
1 hour ago
|
show 3 more comments
I don't think it's possible to satisfy "Ifdir2
exists, I want the command to fail" portably; POSIX requiresrename
to delete an empty dir2 and succeed.
– Michael Homer
2 hours ago
The spec text: "If the old argument points to the pathname of a directory, the new argument shall not point to the pathname of a file that is not a directory. If the directory named by the new argument exists, it shall be removed and old renamed to new. [...] If new names an existing directory, it shall be required to be an empty directory.". That also applies torenameat
. I don't believe there can be any portable method to rename a file that does not go through that path. Given that, which of your requirements can you relax? What sorts of race condition are you concerned with?
– Michael Homer
2 hours ago
Related: mv: Move file only if destination does not exist
– Freddy
2 hours ago
@MichaelHomer: Interesting, thanks. The race condition I'm trying to avoid isdir1
landing insidedir2
, which can happen if multiple processes try to run this command at once. However, I guess it would be fine if an emptydir2
were deleted. Would that help? Also, if there's still no single POSIX solution, I'd be interested in knowing if there are even platform-specific solution that I can call. E.g. is there a solution that works on Mac, let alone other platforms? I haven't found any.
– Mehrdad
2 hours ago
Therenameat2
system call takes a flag argument and one such flag isRENAME_NOREPLACE
which causes it to: "Don't overwrite newpath of the rename. Return an error if newpath already exists." ... But that doesn't really satisfy "portable", so not sure it solves your problem...
– filbranden
1 hour ago
I don't think it's possible to satisfy "If
dir2
exists, I want the command to fail" portably; POSIX requires rename
to delete an empty dir2 and succeed.– Michael Homer
2 hours ago
I don't think it's possible to satisfy "If
dir2
exists, I want the command to fail" portably; POSIX requires rename
to delete an empty dir2 and succeed.– Michael Homer
2 hours ago
The spec text: "If the old argument points to the pathname of a directory, the new argument shall not point to the pathname of a file that is not a directory. If the directory named by the new argument exists, it shall be removed and old renamed to new. [...] If new names an existing directory, it shall be required to be an empty directory.". That also applies to
renameat
. I don't believe there can be any portable method to rename a file that does not go through that path. Given that, which of your requirements can you relax? What sorts of race condition are you concerned with?– Michael Homer
2 hours ago
The spec text: "If the old argument points to the pathname of a directory, the new argument shall not point to the pathname of a file that is not a directory. If the directory named by the new argument exists, it shall be removed and old renamed to new. [...] If new names an existing directory, it shall be required to be an empty directory.". That also applies to
renameat
. I don't believe there can be any portable method to rename a file that does not go through that path. Given that, which of your requirements can you relax? What sorts of race condition are you concerned with?– Michael Homer
2 hours ago
Related: mv: Move file only if destination does not exist
– Freddy
2 hours ago
Related: mv: Move file only if destination does not exist
– Freddy
2 hours ago
@MichaelHomer: Interesting, thanks. The race condition I'm trying to avoid is
dir1
landing inside dir2
, which can happen if multiple processes try to run this command at once. However, I guess it would be fine if an empty dir2
were deleted. Would that help? Also, if there's still no single POSIX solution, I'd be interested in knowing if there are even platform-specific solution that I can call. E.g. is there a solution that works on Mac, let alone other platforms? I haven't found any.– Mehrdad
2 hours ago
@MichaelHomer: Interesting, thanks. The race condition I'm trying to avoid is
dir1
landing inside dir2
, which can happen if multiple processes try to run this command at once. However, I guess it would be fine if an empty dir2
were deleted. Would that help? Also, if there's still no single POSIX solution, I'd be interested in knowing if there are even platform-specific solution that I can call. E.g. is there a solution that works on Mac, let alone other platforms? I haven't found any.– Mehrdad
2 hours ago
The
renameat2
system call takes a flag argument and one such flag is RENAME_NOREPLACE
which causes it to: "Don't overwrite newpath of the rename. Return an error if newpath already exists." ... But that doesn't really satisfy "portable", so not sure it solves your problem...– filbranden
1 hour ago
The
renameat2
system call takes a flag argument and one such flag is RENAME_NOREPLACE
which causes it to: "Don't overwrite newpath of the rename. Return an error if newpath already exists." ... But that doesn't really satisfy "portable", so not sure it solves your problem...– filbranden
1 hour ago
|
show 3 more comments
0
active
oldest
votes
Your Answer
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "106"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f503036%2fportable-race-free-equivalent-of-mv-t-dir1-dir2%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
0
active
oldest
votes
0
active
oldest
votes
active
oldest
votes
active
oldest
votes
Thanks for contributing an answer to Unix & Linux Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f503036%2fportable-race-free-equivalent-of-mv-t-dir1-dir2%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
I don't think it's possible to satisfy "If
dir2
exists, I want the command to fail" portably; POSIX requiresrename
to delete an empty dir2 and succeed.– Michael Homer
2 hours ago
The spec text: "If the old argument points to the pathname of a directory, the new argument shall not point to the pathname of a file that is not a directory. If the directory named by the new argument exists, it shall be removed and old renamed to new. [...] If new names an existing directory, it shall be required to be an empty directory.". That also applies to
renameat
. I don't believe there can be any portable method to rename a file that does not go through that path. Given that, which of your requirements can you relax? What sorts of race condition are you concerned with?– Michael Homer
2 hours ago
Related: mv: Move file only if destination does not exist
– Freddy
2 hours ago
@MichaelHomer: Interesting, thanks. The race condition I'm trying to avoid is
dir1
landing insidedir2
, which can happen if multiple processes try to run this command at once. However, I guess it would be fine if an emptydir2
were deleted. Would that help? Also, if there's still no single POSIX solution, I'd be interested in knowing if there are even platform-specific solution that I can call. E.g. is there a solution that works on Mac, let alone other platforms? I haven't found any.– Mehrdad
2 hours ago
The
renameat2
system call takes a flag argument and one such flag isRENAME_NOREPLACE
which causes it to: "Don't overwrite newpath of the rename. Return an error if newpath already exists." ... But that doesn't really satisfy "portable", so not sure it solves your problem...– filbranden
1 hour ago