Move or copy without overwrite and check success
Clash Royale CLAN TAG#URR8PPP
Problem:
I'm looking for a way to rename or copy a file without overwriting the destination file, if it exists, and then check the success of the move or copy operation. I'm seeking a method that will work with the BSD versions of mv/cp installed on MacOS/Unix, and also the GNU coreutils versions I have on Linux.
Solution attempt:
In all versions of mv/cp, I can prevent overwriting the destination file with the -n
flag:
mv -n file1 file2
cp -n file1 file2
Similar questions suggest testing the success of mv and cp using the exit status, which is 0 if successful and >0 if an error occurred. However, for both versions of mv/cp, the exit code is 0 when the destination file already exists and the -n
flag is used.
The only other option I can think of is to also use the -v
flag, and look at the output of the command:
mv -nv file1 file2
cp -nv file1 file2
However, the GNU and BSD versions of mv/cp behave differently when the -nv
flags are used and file2 already exists: the GNU versions of mv/cp return nothing, whereas the BSD versions return file2 not overwritten
.
Our previous method was to check whether the destination file exists first, then do the mv/cp operation. Believe it or not, this caused problems because the destination file would sometimes get created by another process between the time that the check was performed and the mv/cp operation was executed.
Is there a way to accomplish this task that works with both BSD and GNU versions of mv/cp?
Alternatively, is there are way to do this using Python 2? I couldn't find a way to do this using os.rename()
cp mv
add a comment |
Problem:
I'm looking for a way to rename or copy a file without overwriting the destination file, if it exists, and then check the success of the move or copy operation. I'm seeking a method that will work with the BSD versions of mv/cp installed on MacOS/Unix, and also the GNU coreutils versions I have on Linux.
Solution attempt:
In all versions of mv/cp, I can prevent overwriting the destination file with the -n
flag:
mv -n file1 file2
cp -n file1 file2
Similar questions suggest testing the success of mv and cp using the exit status, which is 0 if successful and >0 if an error occurred. However, for both versions of mv/cp, the exit code is 0 when the destination file already exists and the -n
flag is used.
The only other option I can think of is to also use the -v
flag, and look at the output of the command:
mv -nv file1 file2
cp -nv file1 file2
However, the GNU and BSD versions of mv/cp behave differently when the -nv
flags are used and file2 already exists: the GNU versions of mv/cp return nothing, whereas the BSD versions return file2 not overwritten
.
Our previous method was to check whether the destination file exists first, then do the mv/cp operation. Believe it or not, this caused problems because the destination file would sometimes get created by another process between the time that the check was performed and the mv/cp operation was executed.
Is there a way to accomplish this task that works with both BSD and GNU versions of mv/cp?
Alternatively, is there are way to do this using Python 2? I couldn't find a way to do this using os.rename()
cp mv
RENAME_NOREPLACE
is a relatively recent addition in Linux, I think not present at all in BSD.
– sourcejedi
Jan 25 at 19:57
add a comment |
Problem:
I'm looking for a way to rename or copy a file without overwriting the destination file, if it exists, and then check the success of the move or copy operation. I'm seeking a method that will work with the BSD versions of mv/cp installed on MacOS/Unix, and also the GNU coreutils versions I have on Linux.
Solution attempt:
In all versions of mv/cp, I can prevent overwriting the destination file with the -n
flag:
mv -n file1 file2
cp -n file1 file2
Similar questions suggest testing the success of mv and cp using the exit status, which is 0 if successful and >0 if an error occurred. However, for both versions of mv/cp, the exit code is 0 when the destination file already exists and the -n
flag is used.
The only other option I can think of is to also use the -v
flag, and look at the output of the command:
mv -nv file1 file2
cp -nv file1 file2
However, the GNU and BSD versions of mv/cp behave differently when the -nv
flags are used and file2 already exists: the GNU versions of mv/cp return nothing, whereas the BSD versions return file2 not overwritten
.
Our previous method was to check whether the destination file exists first, then do the mv/cp operation. Believe it or not, this caused problems because the destination file would sometimes get created by another process between the time that the check was performed and the mv/cp operation was executed.
Is there a way to accomplish this task that works with both BSD and GNU versions of mv/cp?
Alternatively, is there are way to do this using Python 2? I couldn't find a way to do this using os.rename()
cp mv
Problem:
I'm looking for a way to rename or copy a file without overwriting the destination file, if it exists, and then check the success of the move or copy operation. I'm seeking a method that will work with the BSD versions of mv/cp installed on MacOS/Unix, and also the GNU coreutils versions I have on Linux.
Solution attempt:
In all versions of mv/cp, I can prevent overwriting the destination file with the -n
flag:
mv -n file1 file2
cp -n file1 file2
Similar questions suggest testing the success of mv and cp using the exit status, which is 0 if successful and >0 if an error occurred. However, for both versions of mv/cp, the exit code is 0 when the destination file already exists and the -n
flag is used.
The only other option I can think of is to also use the -v
flag, and look at the output of the command:
mv -nv file1 file2
cp -nv file1 file2
However, the GNU and BSD versions of mv/cp behave differently when the -nv
flags are used and file2 already exists: the GNU versions of mv/cp return nothing, whereas the BSD versions return file2 not overwritten
.
Our previous method was to check whether the destination file exists first, then do the mv/cp operation. Believe it or not, this caused problems because the destination file would sometimes get created by another process between the time that the check was performed and the mv/cp operation was executed.
Is there a way to accomplish this task that works with both BSD and GNU versions of mv/cp?
Alternatively, is there are way to do this using Python 2? I couldn't find a way to do this using os.rename()
cp mv
cp mv
edited Jan 25 at 18:55
srcerer
asked Jan 25 at 18:46
srcerersrcerer
11
11
RENAME_NOREPLACE
is a relatively recent addition in Linux, I think not present at all in BSD.
– sourcejedi
Jan 25 at 19:57
add a comment |
RENAME_NOREPLACE
is a relatively recent addition in Linux, I think not present at all in BSD.
– sourcejedi
Jan 25 at 19:57
RENAME_NOREPLACE
is a relatively recent addition in Linux, I think not present at all in BSD.– sourcejedi
Jan 25 at 19:57
RENAME_NOREPLACE
is a relatively recent addition in Linux, I think not present at all in BSD.– sourcejedi
Jan 25 at 19:57
add a comment |
2 Answers
2
active
oldest
votes
If you have bash
- https://stackoverflow.com/questions/13828544/atomic-create-file-if-not-exists-from-bash-script
set -o noclobber
> file ; &> /dev/null
This command creates a file named file if there's no existent file
named file. If there's a file named file, then do nothing (but return
a non-zero return code).
I.e. create an empty file first using this technique. If that succeeds, you can then overwrite the empty file.
Similarly for python. Use os.open()
to create an empty file, making sure to include O_EXCL
in the flags. ("For a description of the flag and mode values, see the C run-time documentation." See POSIX standard / Linux man page).
The bash technique is using O_EXCL
behind the scenes. There is also RENAME_NOREPLACE
, but it is a relatively recent addition in Linux, and I do not think it is present on OS X.
1
I guess you meant do something likeos.open("file", os.O_CREAT|os.O_EXCL)
?
– srcerer
Jan 25 at 20:20
Sorry, I can't upvote your answer due to my noobness. If you upvote my question I might pass the 15 reputation required to upvote your answer!
– srcerer
Jan 25 at 20:27
Hi @srcerer, no sweat. Marking the answer as the accepted one (if that's what you want to do) gives more rep anyway.
– sourcejedi
Jan 25 at 21:05
I have edited and linked to reference documentation for os.open(). I am being lazy here and just pointing you towardsO_EXCL
, didn't feel like checking through all the implications (in two different languages). If you want to accept (and/or write) an answer that provides more detail, that's fine.
– sourcejedi
Jan 25 at 21:17
I don't want to mark it as accepted because it's such a lame question (as indicated by the 0 upvotes). Who cares if someone with 1 rep accepts your answer anyhow, am I right?
– srcerer
Jan 25 at 21:18
|
show 3 more comments
FreeBSD does indeed return failure if cp -n
is asked to overwrite a file:
$ rm -f foo.*
$ date > foo.1
$ date > foo.2
$ # this should fail
$ cp -n foo.1 foo.2 || echo fail
fail
$ rm foo.2
$ # this should succeed
$ cp -n foo.1 foo.2 || echo fail
$ exit
You are correct when you state that FreeBSD's mv
returns success even when the destination exists:
$ rm -f foo.*
$ date > foo.1
$ date > foo.2
$ # this should fail
$ mv -n foo.1 foo.2 || echo fail
$ exit
One workaround is to &&
the mv
result code with [ ! -f src-file ]
, as in:
$ rm -f foo.*
$ date > foo.1
$ date > foo.2
$ # this should fail
$ ( mv -n foo.1 foo.2 && [ ! -f foo.1 ] ) || echo fail
fail
$ rm foo.2
$ # this should succeed
$ ( mv -n foo.1 foo.2 && [ ! -f foo.1 ] ) || echo fail
$ exit
Under GNU, neither utility performs the way you would like. The same workaround for mv
works for me on Ubuntu, so that leaves GNU cp
as as the one remaining problem case.
Just as an aside, I hear your comment about the race condition with testing for the destination file before calling cp
, but it strikes me that the same race condition would be present even if cp
did the right thing. The window of opportunity might be smaller, but my intuition is that it would still be there. IANAE, however.
Since the workaround for mv
works on both platforms, perhaps this workaround will suffice:
$ rm -f foo.*
$ date > foo.1
$ date > foo.2
$ # this should fail
$ ( cp -n foo.1 TEMPFILE && mv -n TEMPFILE foo.2 && [ ! -f TEMPFILE ] ) || echo fail
fail
$ rm -f TEMPFILE
$ rm foo.2
$ # this should succeed
$ ( cp -n foo.1 TEMPFILE && mv -n TEMPFILE foo.2 && [ ! -f TEMPFILE ] ) || echo fail
$ rm -f TEMPFILE
$ exit
add a comment |
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%2f496734%2fmove-or-copy-without-overwrite-and-check-success%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
If you have bash
- https://stackoverflow.com/questions/13828544/atomic-create-file-if-not-exists-from-bash-script
set -o noclobber
> file ; &> /dev/null
This command creates a file named file if there's no existent file
named file. If there's a file named file, then do nothing (but return
a non-zero return code).
I.e. create an empty file first using this technique. If that succeeds, you can then overwrite the empty file.
Similarly for python. Use os.open()
to create an empty file, making sure to include O_EXCL
in the flags. ("For a description of the flag and mode values, see the C run-time documentation." See POSIX standard / Linux man page).
The bash technique is using O_EXCL
behind the scenes. There is also RENAME_NOREPLACE
, but it is a relatively recent addition in Linux, and I do not think it is present on OS X.
1
I guess you meant do something likeos.open("file", os.O_CREAT|os.O_EXCL)
?
– srcerer
Jan 25 at 20:20
Sorry, I can't upvote your answer due to my noobness. If you upvote my question I might pass the 15 reputation required to upvote your answer!
– srcerer
Jan 25 at 20:27
Hi @srcerer, no sweat. Marking the answer as the accepted one (if that's what you want to do) gives more rep anyway.
– sourcejedi
Jan 25 at 21:05
I have edited and linked to reference documentation for os.open(). I am being lazy here and just pointing you towardsO_EXCL
, didn't feel like checking through all the implications (in two different languages). If you want to accept (and/or write) an answer that provides more detail, that's fine.
– sourcejedi
Jan 25 at 21:17
I don't want to mark it as accepted because it's such a lame question (as indicated by the 0 upvotes). Who cares if someone with 1 rep accepts your answer anyhow, am I right?
– srcerer
Jan 25 at 21:18
|
show 3 more comments
If you have bash
- https://stackoverflow.com/questions/13828544/atomic-create-file-if-not-exists-from-bash-script
set -o noclobber
> file ; &> /dev/null
This command creates a file named file if there's no existent file
named file. If there's a file named file, then do nothing (but return
a non-zero return code).
I.e. create an empty file first using this technique. If that succeeds, you can then overwrite the empty file.
Similarly for python. Use os.open()
to create an empty file, making sure to include O_EXCL
in the flags. ("For a description of the flag and mode values, see the C run-time documentation." See POSIX standard / Linux man page).
The bash technique is using O_EXCL
behind the scenes. There is also RENAME_NOREPLACE
, but it is a relatively recent addition in Linux, and I do not think it is present on OS X.
1
I guess you meant do something likeos.open("file", os.O_CREAT|os.O_EXCL)
?
– srcerer
Jan 25 at 20:20
Sorry, I can't upvote your answer due to my noobness. If you upvote my question I might pass the 15 reputation required to upvote your answer!
– srcerer
Jan 25 at 20:27
Hi @srcerer, no sweat. Marking the answer as the accepted one (if that's what you want to do) gives more rep anyway.
– sourcejedi
Jan 25 at 21:05
I have edited and linked to reference documentation for os.open(). I am being lazy here and just pointing you towardsO_EXCL
, didn't feel like checking through all the implications (in two different languages). If you want to accept (and/or write) an answer that provides more detail, that's fine.
– sourcejedi
Jan 25 at 21:17
I don't want to mark it as accepted because it's such a lame question (as indicated by the 0 upvotes). Who cares if someone with 1 rep accepts your answer anyhow, am I right?
– srcerer
Jan 25 at 21:18
|
show 3 more comments
If you have bash
- https://stackoverflow.com/questions/13828544/atomic-create-file-if-not-exists-from-bash-script
set -o noclobber
> file ; &> /dev/null
This command creates a file named file if there's no existent file
named file. If there's a file named file, then do nothing (but return
a non-zero return code).
I.e. create an empty file first using this technique. If that succeeds, you can then overwrite the empty file.
Similarly for python. Use os.open()
to create an empty file, making sure to include O_EXCL
in the flags. ("For a description of the flag and mode values, see the C run-time documentation." See POSIX standard / Linux man page).
The bash technique is using O_EXCL
behind the scenes. There is also RENAME_NOREPLACE
, but it is a relatively recent addition in Linux, and I do not think it is present on OS X.
If you have bash
- https://stackoverflow.com/questions/13828544/atomic-create-file-if-not-exists-from-bash-script
set -o noclobber
> file ; &> /dev/null
This command creates a file named file if there's no existent file
named file. If there's a file named file, then do nothing (but return
a non-zero return code).
I.e. create an empty file first using this technique. If that succeeds, you can then overwrite the empty file.
Similarly for python. Use os.open()
to create an empty file, making sure to include O_EXCL
in the flags. ("For a description of the flag and mode values, see the C run-time documentation." See POSIX standard / Linux man page).
The bash technique is using O_EXCL
behind the scenes. There is also RENAME_NOREPLACE
, but it is a relatively recent addition in Linux, and I do not think it is present on OS X.
edited Jan 25 at 21:03
answered Jan 25 at 19:58
sourcejedisourcejedi
24.3k440107
24.3k440107
1
I guess you meant do something likeos.open("file", os.O_CREAT|os.O_EXCL)
?
– srcerer
Jan 25 at 20:20
Sorry, I can't upvote your answer due to my noobness. If you upvote my question I might pass the 15 reputation required to upvote your answer!
– srcerer
Jan 25 at 20:27
Hi @srcerer, no sweat. Marking the answer as the accepted one (if that's what you want to do) gives more rep anyway.
– sourcejedi
Jan 25 at 21:05
I have edited and linked to reference documentation for os.open(). I am being lazy here and just pointing you towardsO_EXCL
, didn't feel like checking through all the implications (in two different languages). If you want to accept (and/or write) an answer that provides more detail, that's fine.
– sourcejedi
Jan 25 at 21:17
I don't want to mark it as accepted because it's such a lame question (as indicated by the 0 upvotes). Who cares if someone with 1 rep accepts your answer anyhow, am I right?
– srcerer
Jan 25 at 21:18
|
show 3 more comments
1
I guess you meant do something likeos.open("file", os.O_CREAT|os.O_EXCL)
?
– srcerer
Jan 25 at 20:20
Sorry, I can't upvote your answer due to my noobness. If you upvote my question I might pass the 15 reputation required to upvote your answer!
– srcerer
Jan 25 at 20:27
Hi @srcerer, no sweat. Marking the answer as the accepted one (if that's what you want to do) gives more rep anyway.
– sourcejedi
Jan 25 at 21:05
I have edited and linked to reference documentation for os.open(). I am being lazy here and just pointing you towardsO_EXCL
, didn't feel like checking through all the implications (in two different languages). If you want to accept (and/or write) an answer that provides more detail, that's fine.
– sourcejedi
Jan 25 at 21:17
I don't want to mark it as accepted because it's such a lame question (as indicated by the 0 upvotes). Who cares if someone with 1 rep accepts your answer anyhow, am I right?
– srcerer
Jan 25 at 21:18
1
1
I guess you meant do something like
os.open("file", os.O_CREAT|os.O_EXCL)
?– srcerer
Jan 25 at 20:20
I guess you meant do something like
os.open("file", os.O_CREAT|os.O_EXCL)
?– srcerer
Jan 25 at 20:20
Sorry, I can't upvote your answer due to my noobness. If you upvote my question I might pass the 15 reputation required to upvote your answer!
– srcerer
Jan 25 at 20:27
Sorry, I can't upvote your answer due to my noobness. If you upvote my question I might pass the 15 reputation required to upvote your answer!
– srcerer
Jan 25 at 20:27
Hi @srcerer, no sweat. Marking the answer as the accepted one (if that's what you want to do) gives more rep anyway.
– sourcejedi
Jan 25 at 21:05
Hi @srcerer, no sweat. Marking the answer as the accepted one (if that's what you want to do) gives more rep anyway.
– sourcejedi
Jan 25 at 21:05
I have edited and linked to reference documentation for os.open(). I am being lazy here and just pointing you towards
O_EXCL
, didn't feel like checking through all the implications (in two different languages). If you want to accept (and/or write) an answer that provides more detail, that's fine.– sourcejedi
Jan 25 at 21:17
I have edited and linked to reference documentation for os.open(). I am being lazy here and just pointing you towards
O_EXCL
, didn't feel like checking through all the implications (in two different languages). If you want to accept (and/or write) an answer that provides more detail, that's fine.– sourcejedi
Jan 25 at 21:17
I don't want to mark it as accepted because it's such a lame question (as indicated by the 0 upvotes). Who cares if someone with 1 rep accepts your answer anyhow, am I right?
– srcerer
Jan 25 at 21:18
I don't want to mark it as accepted because it's such a lame question (as indicated by the 0 upvotes). Who cares if someone with 1 rep accepts your answer anyhow, am I right?
– srcerer
Jan 25 at 21:18
|
show 3 more comments
FreeBSD does indeed return failure if cp -n
is asked to overwrite a file:
$ rm -f foo.*
$ date > foo.1
$ date > foo.2
$ # this should fail
$ cp -n foo.1 foo.2 || echo fail
fail
$ rm foo.2
$ # this should succeed
$ cp -n foo.1 foo.2 || echo fail
$ exit
You are correct when you state that FreeBSD's mv
returns success even when the destination exists:
$ rm -f foo.*
$ date > foo.1
$ date > foo.2
$ # this should fail
$ mv -n foo.1 foo.2 || echo fail
$ exit
One workaround is to &&
the mv
result code with [ ! -f src-file ]
, as in:
$ rm -f foo.*
$ date > foo.1
$ date > foo.2
$ # this should fail
$ ( mv -n foo.1 foo.2 && [ ! -f foo.1 ] ) || echo fail
fail
$ rm foo.2
$ # this should succeed
$ ( mv -n foo.1 foo.2 && [ ! -f foo.1 ] ) || echo fail
$ exit
Under GNU, neither utility performs the way you would like. The same workaround for mv
works for me on Ubuntu, so that leaves GNU cp
as as the one remaining problem case.
Just as an aside, I hear your comment about the race condition with testing for the destination file before calling cp
, but it strikes me that the same race condition would be present even if cp
did the right thing. The window of opportunity might be smaller, but my intuition is that it would still be there. IANAE, however.
Since the workaround for mv
works on both platforms, perhaps this workaround will suffice:
$ rm -f foo.*
$ date > foo.1
$ date > foo.2
$ # this should fail
$ ( cp -n foo.1 TEMPFILE && mv -n TEMPFILE foo.2 && [ ! -f TEMPFILE ] ) || echo fail
fail
$ rm -f TEMPFILE
$ rm foo.2
$ # this should succeed
$ ( cp -n foo.1 TEMPFILE && mv -n TEMPFILE foo.2 && [ ! -f TEMPFILE ] ) || echo fail
$ rm -f TEMPFILE
$ exit
add a comment |
FreeBSD does indeed return failure if cp -n
is asked to overwrite a file:
$ rm -f foo.*
$ date > foo.1
$ date > foo.2
$ # this should fail
$ cp -n foo.1 foo.2 || echo fail
fail
$ rm foo.2
$ # this should succeed
$ cp -n foo.1 foo.2 || echo fail
$ exit
You are correct when you state that FreeBSD's mv
returns success even when the destination exists:
$ rm -f foo.*
$ date > foo.1
$ date > foo.2
$ # this should fail
$ mv -n foo.1 foo.2 || echo fail
$ exit
One workaround is to &&
the mv
result code with [ ! -f src-file ]
, as in:
$ rm -f foo.*
$ date > foo.1
$ date > foo.2
$ # this should fail
$ ( mv -n foo.1 foo.2 && [ ! -f foo.1 ] ) || echo fail
fail
$ rm foo.2
$ # this should succeed
$ ( mv -n foo.1 foo.2 && [ ! -f foo.1 ] ) || echo fail
$ exit
Under GNU, neither utility performs the way you would like. The same workaround for mv
works for me on Ubuntu, so that leaves GNU cp
as as the one remaining problem case.
Just as an aside, I hear your comment about the race condition with testing for the destination file before calling cp
, but it strikes me that the same race condition would be present even if cp
did the right thing. The window of opportunity might be smaller, but my intuition is that it would still be there. IANAE, however.
Since the workaround for mv
works on both platforms, perhaps this workaround will suffice:
$ rm -f foo.*
$ date > foo.1
$ date > foo.2
$ # this should fail
$ ( cp -n foo.1 TEMPFILE && mv -n TEMPFILE foo.2 && [ ! -f TEMPFILE ] ) || echo fail
fail
$ rm -f TEMPFILE
$ rm foo.2
$ # this should succeed
$ ( cp -n foo.1 TEMPFILE && mv -n TEMPFILE foo.2 && [ ! -f TEMPFILE ] ) || echo fail
$ rm -f TEMPFILE
$ exit
add a comment |
FreeBSD does indeed return failure if cp -n
is asked to overwrite a file:
$ rm -f foo.*
$ date > foo.1
$ date > foo.2
$ # this should fail
$ cp -n foo.1 foo.2 || echo fail
fail
$ rm foo.2
$ # this should succeed
$ cp -n foo.1 foo.2 || echo fail
$ exit
You are correct when you state that FreeBSD's mv
returns success even when the destination exists:
$ rm -f foo.*
$ date > foo.1
$ date > foo.2
$ # this should fail
$ mv -n foo.1 foo.2 || echo fail
$ exit
One workaround is to &&
the mv
result code with [ ! -f src-file ]
, as in:
$ rm -f foo.*
$ date > foo.1
$ date > foo.2
$ # this should fail
$ ( mv -n foo.1 foo.2 && [ ! -f foo.1 ] ) || echo fail
fail
$ rm foo.2
$ # this should succeed
$ ( mv -n foo.1 foo.2 && [ ! -f foo.1 ] ) || echo fail
$ exit
Under GNU, neither utility performs the way you would like. The same workaround for mv
works for me on Ubuntu, so that leaves GNU cp
as as the one remaining problem case.
Just as an aside, I hear your comment about the race condition with testing for the destination file before calling cp
, but it strikes me that the same race condition would be present even if cp
did the right thing. The window of opportunity might be smaller, but my intuition is that it would still be there. IANAE, however.
Since the workaround for mv
works on both platforms, perhaps this workaround will suffice:
$ rm -f foo.*
$ date > foo.1
$ date > foo.2
$ # this should fail
$ ( cp -n foo.1 TEMPFILE && mv -n TEMPFILE foo.2 && [ ! -f TEMPFILE ] ) || echo fail
fail
$ rm -f TEMPFILE
$ rm foo.2
$ # this should succeed
$ ( cp -n foo.1 TEMPFILE && mv -n TEMPFILE foo.2 && [ ! -f TEMPFILE ] ) || echo fail
$ rm -f TEMPFILE
$ exit
FreeBSD does indeed return failure if cp -n
is asked to overwrite a file:
$ rm -f foo.*
$ date > foo.1
$ date > foo.2
$ # this should fail
$ cp -n foo.1 foo.2 || echo fail
fail
$ rm foo.2
$ # this should succeed
$ cp -n foo.1 foo.2 || echo fail
$ exit
You are correct when you state that FreeBSD's mv
returns success even when the destination exists:
$ rm -f foo.*
$ date > foo.1
$ date > foo.2
$ # this should fail
$ mv -n foo.1 foo.2 || echo fail
$ exit
One workaround is to &&
the mv
result code with [ ! -f src-file ]
, as in:
$ rm -f foo.*
$ date > foo.1
$ date > foo.2
$ # this should fail
$ ( mv -n foo.1 foo.2 && [ ! -f foo.1 ] ) || echo fail
fail
$ rm foo.2
$ # this should succeed
$ ( mv -n foo.1 foo.2 && [ ! -f foo.1 ] ) || echo fail
$ exit
Under GNU, neither utility performs the way you would like. The same workaround for mv
works for me on Ubuntu, so that leaves GNU cp
as as the one remaining problem case.
Just as an aside, I hear your comment about the race condition with testing for the destination file before calling cp
, but it strikes me that the same race condition would be present even if cp
did the right thing. The window of opportunity might be smaller, but my intuition is that it would still be there. IANAE, however.
Since the workaround for mv
works on both platforms, perhaps this workaround will suffice:
$ rm -f foo.*
$ date > foo.1
$ date > foo.2
$ # this should fail
$ ( cp -n foo.1 TEMPFILE && mv -n TEMPFILE foo.2 && [ ! -f TEMPFILE ] ) || echo fail
fail
$ rm -f TEMPFILE
$ rm foo.2
$ # this should succeed
$ ( cp -n foo.1 TEMPFILE && mv -n TEMPFILE foo.2 && [ ! -f TEMPFILE ] ) || echo fail
$ rm -f TEMPFILE
$ exit
answered Jan 25 at 22:48
Jim L.Jim L.
1313
1313
add a comment |
add a comment |
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%2f496734%2fmove-or-copy-without-overwrite-and-check-success%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
RENAME_NOREPLACE
is a relatively recent addition in Linux, I think not present at all in BSD.– sourcejedi
Jan 25 at 19:57