How do I create numbered backups?












1















Some GNU utils (e.g., mv and cp) can create numbered backups (foo.~1~).
Others (e.g., wget) cannot.
I would like to create numbered backups before running tools which overwrite files by default.
Here is a bash function which appears to do what I need:



backup(){                       # back up the file, emacs style
file=$1
if test -f "${file}"; then
/bin/mv --backup=numbered "$(mktemp ${file}XXX)" "${file}"
/bin/rm "${file}"
fi
}


to be used, e.g., like this:



backup foo
curl http://.... > foo


I wonder if there is a better way.










share|improve this question

























  • Apart from the fact that the script obviously breaks with files that contain whitespace in their path—which can be easily fixed though—why are you asking if there's anything "better"? Better in what aspect?

    – slhck
    Aug 20 '13 at 20:58






  • 1





    @slhck: thanks for the bug catch - should be fixed. "better" - maybe I am missing something obvious and I do not need these 7 lines? maybe there is a trivial one-liner?

    – sds
    Aug 20 '13 at 21:14
















1















Some GNU utils (e.g., mv and cp) can create numbered backups (foo.~1~).
Others (e.g., wget) cannot.
I would like to create numbered backups before running tools which overwrite files by default.
Here is a bash function which appears to do what I need:



backup(){                       # back up the file, emacs style
file=$1
if test -f "${file}"; then
/bin/mv --backup=numbered "$(mktemp ${file}XXX)" "${file}"
/bin/rm "${file}"
fi
}


to be used, e.g., like this:



backup foo
curl http://.... > foo


I wonder if there is a better way.










share|improve this question

























  • Apart from the fact that the script obviously breaks with files that contain whitespace in their path—which can be easily fixed though—why are you asking if there's anything "better"? Better in what aspect?

    – slhck
    Aug 20 '13 at 20:58






  • 1





    @slhck: thanks for the bug catch - should be fixed. "better" - maybe I am missing something obvious and I do not need these 7 lines? maybe there is a trivial one-liner?

    – sds
    Aug 20 '13 at 21:14














1












1








1








Some GNU utils (e.g., mv and cp) can create numbered backups (foo.~1~).
Others (e.g., wget) cannot.
I would like to create numbered backups before running tools which overwrite files by default.
Here is a bash function which appears to do what I need:



backup(){                       # back up the file, emacs style
file=$1
if test -f "${file}"; then
/bin/mv --backup=numbered "$(mktemp ${file}XXX)" "${file}"
/bin/rm "${file}"
fi
}


to be used, e.g., like this:



backup foo
curl http://.... > foo


I wonder if there is a better way.










share|improve this question
















Some GNU utils (e.g., mv and cp) can create numbered backups (foo.~1~).
Others (e.g., wget) cannot.
I would like to create numbered backups before running tools which overwrite files by default.
Here is a bash function which appears to do what I need:



backup(){                       # back up the file, emacs style
file=$1
if test -f "${file}"; then
/bin/mv --backup=numbered "$(mktemp ${file}XXX)" "${file}"
/bin/rm "${file}"
fi
}


to be used, e.g., like this:



backup foo
curl http://.... > foo


I wonder if there is a better way.







backup cp mv






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Aug 20 '13 at 21:11







sds

















asked Aug 20 '13 at 20:18









sdssds

1,24521430




1,24521430













  • Apart from the fact that the script obviously breaks with files that contain whitespace in their path—which can be easily fixed though—why are you asking if there's anything "better"? Better in what aspect?

    – slhck
    Aug 20 '13 at 20:58






  • 1





    @slhck: thanks for the bug catch - should be fixed. "better" - maybe I am missing something obvious and I do not need these 7 lines? maybe there is a trivial one-liner?

    – sds
    Aug 20 '13 at 21:14



















  • Apart from the fact that the script obviously breaks with files that contain whitespace in their path—which can be easily fixed though—why are you asking if there's anything "better"? Better in what aspect?

    – slhck
    Aug 20 '13 at 20:58






  • 1





    @slhck: thanks for the bug catch - should be fixed. "better" - maybe I am missing something obvious and I do not need these 7 lines? maybe there is a trivial one-liner?

    – sds
    Aug 20 '13 at 21:14

















Apart from the fact that the script obviously breaks with files that contain whitespace in their path—which can be easily fixed though—why are you asking if there's anything "better"? Better in what aspect?

– slhck
Aug 20 '13 at 20:58





Apart from the fact that the script obviously breaks with files that contain whitespace in their path—which can be easily fixed though—why are you asking if there's anything "better"? Better in what aspect?

– slhck
Aug 20 '13 at 20:58




1




1





@slhck: thanks for the bug catch - should be fixed. "better" - maybe I am missing something obvious and I do not need these 7 lines? maybe there is a trivial one-liner?

– sds
Aug 20 '13 at 21:14





@slhck: thanks for the bug catch - should be fixed. "better" - maybe I am missing something obvious and I do not need these 7 lines? maybe there is a trivial one-liner?

– sds
Aug 20 '13 at 21:14










2 Answers
2






active

oldest

votes


















1














A small improvement over the OP's solution to make it more generally usefull:




  • Works with directories.

  • The mktemp argument might need quotes, too.

  • I'd && the commands in order not to get an error message from mv if mktemp fails, etc.

  • Added option / argument separators -- in case of filenames which start with a dash.


backup(){                       # back up the file, emacs style
local file=$1
local tmp
if test -e "${file}"; then
tmp=$(mktemp -- "${file}XXX") && /bin/mv --backup=numbered --no-target-dir -- "$tmp" "${file}" && /bin/rm -- "${file}"
fi
}


BTW, cp supports making a numbered backup with source == target.



> cp -v --backup=t --force a a
'a' -> 'a.~4~'





share|improve this answer































    0














    Still not exactly a one liner, but you get closer with one single call to perl together with its powerful e option (ie. execute the substitution part):



    backup(){
    mv "$1" "$(echo $1 |perl -pe '~s|(.*?)(~([0-9]*)~)?$|print "$1~".(${3}+1)."~"|e and exit')"
    }


    Notice the and exit what prevents perl to print the matching count that otherwise pollutes the name.



    You may also want to add 2>/dev/null to the end of the line to keep it quiet when the file does not exist.






    share|improve this answer
























    • This is more complex than my solution; it does not use the --backup option of mv, it emulates it with perl.

      – sds
      Aug 21 '13 at 13:16












    Your Answer








    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "3"
    };
    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: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    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%2fsuperuser.com%2fquestions%2f634390%2fhow-do-i-create-numbered-backups%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














    A small improvement over the OP's solution to make it more generally usefull:




    • Works with directories.

    • The mktemp argument might need quotes, too.

    • I'd && the commands in order not to get an error message from mv if mktemp fails, etc.

    • Added option / argument separators -- in case of filenames which start with a dash.


    backup(){                       # back up the file, emacs style
    local file=$1
    local tmp
    if test -e "${file}"; then
    tmp=$(mktemp -- "${file}XXX") && /bin/mv --backup=numbered --no-target-dir -- "$tmp" "${file}" && /bin/rm -- "${file}"
    fi
    }


    BTW, cp supports making a numbered backup with source == target.



    > cp -v --backup=t --force a a
    'a' -> 'a.~4~'





    share|improve this answer




























      1














      A small improvement over the OP's solution to make it more generally usefull:




      • Works with directories.

      • The mktemp argument might need quotes, too.

      • I'd && the commands in order not to get an error message from mv if mktemp fails, etc.

      • Added option / argument separators -- in case of filenames which start with a dash.


      backup(){                       # back up the file, emacs style
      local file=$1
      local tmp
      if test -e "${file}"; then
      tmp=$(mktemp -- "${file}XXX") && /bin/mv --backup=numbered --no-target-dir -- "$tmp" "${file}" && /bin/rm -- "${file}"
      fi
      }


      BTW, cp supports making a numbered backup with source == target.



      > cp -v --backup=t --force a a
      'a' -> 'a.~4~'





      share|improve this answer


























        1












        1








        1







        A small improvement over the OP's solution to make it more generally usefull:




        • Works with directories.

        • The mktemp argument might need quotes, too.

        • I'd && the commands in order not to get an error message from mv if mktemp fails, etc.

        • Added option / argument separators -- in case of filenames which start with a dash.


        backup(){                       # back up the file, emacs style
        local file=$1
        local tmp
        if test -e "${file}"; then
        tmp=$(mktemp -- "${file}XXX") && /bin/mv --backup=numbered --no-target-dir -- "$tmp" "${file}" && /bin/rm -- "${file}"
        fi
        }


        BTW, cp supports making a numbered backup with source == target.



        > cp -v --backup=t --force a a
        'a' -> 'a.~4~'





        share|improve this answer













        A small improvement over the OP's solution to make it more generally usefull:




        • Works with directories.

        • The mktemp argument might need quotes, too.

        • I'd && the commands in order not to get an error message from mv if mktemp fails, etc.

        • Added option / argument separators -- in case of filenames which start with a dash.


        backup(){                       # back up the file, emacs style
        local file=$1
        local tmp
        if test -e "${file}"; then
        tmp=$(mktemp -- "${file}XXX") && /bin/mv --backup=numbered --no-target-dir -- "$tmp" "${file}" && /bin/rm -- "${file}"
        fi
        }


        BTW, cp supports making a numbered backup with source == target.



        > cp -v --backup=t --force a a
        'a' -> 'a.~4~'






        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Feb 16 at 22:00









        EndlosSchleifeEndlosSchleife

        513




        513

























            0














            Still not exactly a one liner, but you get closer with one single call to perl together with its powerful e option (ie. execute the substitution part):



            backup(){
            mv "$1" "$(echo $1 |perl -pe '~s|(.*?)(~([0-9]*)~)?$|print "$1~".(${3}+1)."~"|e and exit')"
            }


            Notice the and exit what prevents perl to print the matching count that otherwise pollutes the name.



            You may also want to add 2>/dev/null to the end of the line to keep it quiet when the file does not exist.






            share|improve this answer
























            • This is more complex than my solution; it does not use the --backup option of mv, it emulates it with perl.

              – sds
              Aug 21 '13 at 13:16
















            0














            Still not exactly a one liner, but you get closer with one single call to perl together with its powerful e option (ie. execute the substitution part):



            backup(){
            mv "$1" "$(echo $1 |perl -pe '~s|(.*?)(~([0-9]*)~)?$|print "$1~".(${3}+1)."~"|e and exit')"
            }


            Notice the and exit what prevents perl to print the matching count that otherwise pollutes the name.



            You may also want to add 2>/dev/null to the end of the line to keep it quiet when the file does not exist.






            share|improve this answer
























            • This is more complex than my solution; it does not use the --backup option of mv, it emulates it with perl.

              – sds
              Aug 21 '13 at 13:16














            0












            0








            0







            Still not exactly a one liner, but you get closer with one single call to perl together with its powerful e option (ie. execute the substitution part):



            backup(){
            mv "$1" "$(echo $1 |perl -pe '~s|(.*?)(~([0-9]*)~)?$|print "$1~".(${3}+1)."~"|e and exit')"
            }


            Notice the and exit what prevents perl to print the matching count that otherwise pollutes the name.



            You may also want to add 2>/dev/null to the end of the line to keep it quiet when the file does not exist.






            share|improve this answer













            Still not exactly a one liner, but you get closer with one single call to perl together with its powerful e option (ie. execute the substitution part):



            backup(){
            mv "$1" "$(echo $1 |perl -pe '~s|(.*?)(~([0-9]*)~)?$|print "$1~".(${3}+1)."~"|e and exit')"
            }


            Notice the and exit what prevents perl to print the matching count that otherwise pollutes the name.



            You may also want to add 2>/dev/null to the end of the line to keep it quiet when the file does not exist.







            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Aug 21 '13 at 12:06









            MoonCactusMoonCactus

            1135




            1135













            • This is more complex than my solution; it does not use the --backup option of mv, it emulates it with perl.

              – sds
              Aug 21 '13 at 13:16



















            • This is more complex than my solution; it does not use the --backup option of mv, it emulates it with perl.

              – sds
              Aug 21 '13 at 13:16

















            This is more complex than my solution; it does not use the --backup option of mv, it emulates it with perl.

            – sds
            Aug 21 '13 at 13:16





            This is more complex than my solution; it does not use the --backup option of mv, it emulates it with perl.

            – sds
            Aug 21 '13 at 13:16


















            draft saved

            draft discarded




















































            Thanks for contributing an answer to Super User!


            • 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%2fsuperuser.com%2fquestions%2f634390%2fhow-do-i-create-numbered-backups%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

            Mouse cursor on multiple screens with different PPI

            Agildo Ribeiro

            Sometime when accessing a menu: “Ubuntu 16.04 has experienced an internal error”