Move or copy without overwrite and check success

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP












0















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()










share|improve this question
























  • RENAME_NOREPLACE is a relatively recent addition in Linux, I think not present at all in BSD.

    – sourcejedi
    Jan 25 at 19:57















0















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()










share|improve this question
























  • RENAME_NOREPLACE is a relatively recent addition in Linux, I think not present at all in BSD.

    – sourcejedi
    Jan 25 at 19:57













0












0








0








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()










share|improve this question
















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






share|improve this question















share|improve this question













share|improve this question




share|improve this question








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

















  • 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










2 Answers
2






active

oldest

votes


















1














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.






share|improve this answer




















  • 1





    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











  • 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 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


















0














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





share|improve this answer






















    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
    );



    );













    draft saved

    draft discarded


















    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









    1














    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.






    share|improve this answer




















    • 1





      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











    • 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 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














    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.






    share|improve this answer




















    • 1





      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











    • 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 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








    1







    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.






    share|improve this answer















    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.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Jan 25 at 21:03

























    answered Jan 25 at 19:58









    sourcejedisourcejedi

    24.3k440107




    24.3k440107







    • 1





      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











    • 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 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





      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











    • 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 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













    0














    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





    share|improve this answer



























      0














      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





      share|improve this answer

























        0












        0








        0







        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





        share|improve this answer













        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






        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Jan 25 at 22:48









        Jim L.Jim L.

        1313




        1313



























            draft saved

            draft discarded
















































            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.




            draft saved


            draft discarded














            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





















































            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






            Popular posts from this blog

            How to check contact read email or not when send email to Individual?

            Bahrain

            Postfix configuration issue with fips on centos 7; mailgun relay