Backing up dotfiles with a shell script

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











up vote
0
down vote

favorite












A simple shell script is needed to copy dotfiles, adding a .backup extension, i.e., .dotfile1.backup. The script below will not work because it adds extensions to pre-existing backups forever and ever, i.e., .dotfile1.backup.backup.



bkdot.sh



#!/bin/sh
for file in .*; do
cp “./$file” “./$file.backup”
done


The next script seems like it should solve the problem, but nothing happens at all. What is it missing?



bkdot_revised.sh



#!/bin/sh
for file in .*; do
if [ ! “./$file.backup” ]; then
cp “./$file” “./$file.backup”
fi
done









share|improve this question



























    up vote
    0
    down vote

    favorite












    A simple shell script is needed to copy dotfiles, adding a .backup extension, i.e., .dotfile1.backup. The script below will not work because it adds extensions to pre-existing backups forever and ever, i.e., .dotfile1.backup.backup.



    bkdot.sh



    #!/bin/sh
    for file in .*; do
    cp “./$file” “./$file.backup”
    done


    The next script seems like it should solve the problem, but nothing happens at all. What is it missing?



    bkdot_revised.sh



    #!/bin/sh
    for file in .*; do
    if [ ! “./$file.backup” ]; then
    cp “./$file” “./$file.backup”
    fi
    done









    share|improve this question

























      up vote
      0
      down vote

      favorite









      up vote
      0
      down vote

      favorite











      A simple shell script is needed to copy dotfiles, adding a .backup extension, i.e., .dotfile1.backup. The script below will not work because it adds extensions to pre-existing backups forever and ever, i.e., .dotfile1.backup.backup.



      bkdot.sh



      #!/bin/sh
      for file in .*; do
      cp “./$file” “./$file.backup”
      done


      The next script seems like it should solve the problem, but nothing happens at all. What is it missing?



      bkdot_revised.sh



      #!/bin/sh
      for file in .*; do
      if [ ! “./$file.backup” ]; then
      cp “./$file” “./$file.backup”
      fi
      done









      share|improve this question















      A simple shell script is needed to copy dotfiles, adding a .backup extension, i.e., .dotfile1.backup. The script below will not work because it adds extensions to pre-existing backups forever and ever, i.e., .dotfile1.backup.backup.



      bkdot.sh



      #!/bin/sh
      for file in .*; do
      cp “./$file” “./$file.backup”
      done


      The next script seems like it should solve the problem, but nothing happens at all. What is it missing?



      bkdot_revised.sh



      #!/bin/sh
      for file in .*; do
      if [ ! “./$file.backup” ]; then
      cp “./$file” “./$file.backup”
      fi
      done






      shell-script shell






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Dec 7 at 15:05

























      asked Dec 7 at 6:57









      justinnoor.io

      350218




      350218




















          3 Answers
          3






          active

          oldest

          votes

















          up vote
          1
          down vote













          The ! operator just negates it's operand so the condition always evaluates to false.
          There are file test operators, -f for instance that returns true if file exists.



          However I'm not sure you are doing this right, neither only making backup if it doesn't exist nor always overwriting existing backups is secure.



          Could do this way.



          #!/bin/sh
          for file in .*; do
          if [ ! -f "./$file.backup" ]; then
          cp "./$file" "./$file.backup"
          fi
          done





          share|improve this answer




















          • This doesn’t solve the .backup.backup issue.
            – justinnoor.io
            Dec 7 at 15:38

















          up vote
          1
          down vote













          The test [ doesn't have enough information. You need to compare $file to a reference. You current construct says "if not this string", but you need to say "if x is not this string". I would use a regex, i.e. with [[ instead of [. Hence,



          #!/bin/bash
          GLOBIGNORE=.:..
          for file in .*; do
          if [[ ! "$file" =~ .backup$ ]]; then
          cp "$file" "$file.backup"
          fi
          done


          • As per Kusalananda's comment, I moved the shebang to /bin/bash, to ensure the [[ construct works.

          • As per Gordon Davisson's comment, I added the GLOBIGNORE, so that the script doesn't attempt to copy . and ..

          A few other things:




          • ./ in the paths is unnecessary. You are already in this directory!

          • I'm not sure if it was just a copy-paste issue, but you had instead of ".

          • Personally, I would just copy into another directory, and avoid all these issues, and avoid polluting my home directory. Actually, I would just (incrementally) backup everything instead!


          Here is a pure /bin/sh version. Instead of using the [[ bashism, I've used case instead.



          #!/bin/sh
          GLOBIGNORE=.:..
          for file in .*; do
          case "$file" in
          *.backup) ;;
          *) cp "$file" "$file.backup";;
          esac
          done





          share|improve this answer


















          • 1




            Also, this will try to back up . (the entire current directory) and .. (its parent), along with any dot directories (e.g. .ssh)... but fail because cp requires the -R option to do this.
            – Gordon Davisson
            Dec 7 at 7:29










          • @GordonDavisson Good point. I was actually testing with zsh, silly me. I've edited the answer.
            – Sparhawk
            Dec 7 at 8:07






          • 1




            @Kusalananda Thanks. Edited. Yeah, I interpreted the test in the question as looking for the current filename's suffix, rather than testing for a copy of the current file + .backup. It's a bit unclear, but if there were .foo, then .foo.backup were created, then .foo deleted, -f would result in .foo.backup.backup being created… which I assume is not preferred.
            – Sparhawk
            Dec 7 at 8:12










          • It’s not a bash script
            – justinnoor.io
            Dec 7 at 14:00










          • @justinnoor.io What do you mean? This is a bash script. Or are you saying that you do not want a bash script? Your shebang refers to /bin/sh, but depending on the system, this can be ambiguous. On my system (Arch Linux), if I change the shebang to /bin/sh, my script still works. It may well work on yours too.
            – Sparhawk
            Dec 7 at 23:08


















          up vote
          0
          down vote













          Why don't we simply use sed to backup?



          sed -i.bak 's#n#n#' <filepattern*>





          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',
            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%2f486520%2fbacking-up-dotfiles-with-a-shell-script%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown

























            3 Answers
            3






            active

            oldest

            votes








            3 Answers
            3






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes








            up vote
            1
            down vote













            The ! operator just negates it's operand so the condition always evaluates to false.
            There are file test operators, -f for instance that returns true if file exists.



            However I'm not sure you are doing this right, neither only making backup if it doesn't exist nor always overwriting existing backups is secure.



            Could do this way.



            #!/bin/sh
            for file in .*; do
            if [ ! -f "./$file.backup" ]; then
            cp "./$file" "./$file.backup"
            fi
            done





            share|improve this answer




















            • This doesn’t solve the .backup.backup issue.
              – justinnoor.io
              Dec 7 at 15:38














            up vote
            1
            down vote













            The ! operator just negates it's operand so the condition always evaluates to false.
            There are file test operators, -f for instance that returns true if file exists.



            However I'm not sure you are doing this right, neither only making backup if it doesn't exist nor always overwriting existing backups is secure.



            Could do this way.



            #!/bin/sh
            for file in .*; do
            if [ ! -f "./$file.backup" ]; then
            cp "./$file" "./$file.backup"
            fi
            done





            share|improve this answer




















            • This doesn’t solve the .backup.backup issue.
              – justinnoor.io
              Dec 7 at 15:38












            up vote
            1
            down vote










            up vote
            1
            down vote









            The ! operator just negates it's operand so the condition always evaluates to false.
            There are file test operators, -f for instance that returns true if file exists.



            However I'm not sure you are doing this right, neither only making backup if it doesn't exist nor always overwriting existing backups is secure.



            Could do this way.



            #!/bin/sh
            for file in .*; do
            if [ ! -f "./$file.backup" ]; then
            cp "./$file" "./$file.backup"
            fi
            done





            share|improve this answer












            The ! operator just negates it's operand so the condition always evaluates to false.
            There are file test operators, -f for instance that returns true if file exists.



            However I'm not sure you are doing this right, neither only making backup if it doesn't exist nor always overwriting existing backups is secure.



            Could do this way.



            #!/bin/sh
            for file in .*; do
            if [ ! -f "./$file.backup" ]; then
            cp "./$file" "./$file.backup"
            fi
            done






            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Dec 7 at 7:51









            ntj

            164




            164











            • This doesn’t solve the .backup.backup issue.
              – justinnoor.io
              Dec 7 at 15:38
















            • This doesn’t solve the .backup.backup issue.
              – justinnoor.io
              Dec 7 at 15:38















            This doesn’t solve the .backup.backup issue.
            – justinnoor.io
            Dec 7 at 15:38




            This doesn’t solve the .backup.backup issue.
            – justinnoor.io
            Dec 7 at 15:38












            up vote
            1
            down vote













            The test [ doesn't have enough information. You need to compare $file to a reference. You current construct says "if not this string", but you need to say "if x is not this string". I would use a regex, i.e. with [[ instead of [. Hence,



            #!/bin/bash
            GLOBIGNORE=.:..
            for file in .*; do
            if [[ ! "$file" =~ .backup$ ]]; then
            cp "$file" "$file.backup"
            fi
            done


            • As per Kusalananda's comment, I moved the shebang to /bin/bash, to ensure the [[ construct works.

            • As per Gordon Davisson's comment, I added the GLOBIGNORE, so that the script doesn't attempt to copy . and ..

            A few other things:




            • ./ in the paths is unnecessary. You are already in this directory!

            • I'm not sure if it was just a copy-paste issue, but you had instead of ".

            • Personally, I would just copy into another directory, and avoid all these issues, and avoid polluting my home directory. Actually, I would just (incrementally) backup everything instead!


            Here is a pure /bin/sh version. Instead of using the [[ bashism, I've used case instead.



            #!/bin/sh
            GLOBIGNORE=.:..
            for file in .*; do
            case "$file" in
            *.backup) ;;
            *) cp "$file" "$file.backup";;
            esac
            done





            share|improve this answer


















            • 1




              Also, this will try to back up . (the entire current directory) and .. (its parent), along with any dot directories (e.g. .ssh)... but fail because cp requires the -R option to do this.
              – Gordon Davisson
              Dec 7 at 7:29










            • @GordonDavisson Good point. I was actually testing with zsh, silly me. I've edited the answer.
              – Sparhawk
              Dec 7 at 8:07






            • 1




              @Kusalananda Thanks. Edited. Yeah, I interpreted the test in the question as looking for the current filename's suffix, rather than testing for a copy of the current file + .backup. It's a bit unclear, but if there were .foo, then .foo.backup were created, then .foo deleted, -f would result in .foo.backup.backup being created… which I assume is not preferred.
              – Sparhawk
              Dec 7 at 8:12










            • It’s not a bash script
              – justinnoor.io
              Dec 7 at 14:00










            • @justinnoor.io What do you mean? This is a bash script. Or are you saying that you do not want a bash script? Your shebang refers to /bin/sh, but depending on the system, this can be ambiguous. On my system (Arch Linux), if I change the shebang to /bin/sh, my script still works. It may well work on yours too.
              – Sparhawk
              Dec 7 at 23:08















            up vote
            1
            down vote













            The test [ doesn't have enough information. You need to compare $file to a reference. You current construct says "if not this string", but you need to say "if x is not this string". I would use a regex, i.e. with [[ instead of [. Hence,



            #!/bin/bash
            GLOBIGNORE=.:..
            for file in .*; do
            if [[ ! "$file" =~ .backup$ ]]; then
            cp "$file" "$file.backup"
            fi
            done


            • As per Kusalananda's comment, I moved the shebang to /bin/bash, to ensure the [[ construct works.

            • As per Gordon Davisson's comment, I added the GLOBIGNORE, so that the script doesn't attempt to copy . and ..

            A few other things:




            • ./ in the paths is unnecessary. You are already in this directory!

            • I'm not sure if it was just a copy-paste issue, but you had instead of ".

            • Personally, I would just copy into another directory, and avoid all these issues, and avoid polluting my home directory. Actually, I would just (incrementally) backup everything instead!


            Here is a pure /bin/sh version. Instead of using the [[ bashism, I've used case instead.



            #!/bin/sh
            GLOBIGNORE=.:..
            for file in .*; do
            case "$file" in
            *.backup) ;;
            *) cp "$file" "$file.backup";;
            esac
            done





            share|improve this answer


















            • 1




              Also, this will try to back up . (the entire current directory) and .. (its parent), along with any dot directories (e.g. .ssh)... but fail because cp requires the -R option to do this.
              – Gordon Davisson
              Dec 7 at 7:29










            • @GordonDavisson Good point. I was actually testing with zsh, silly me. I've edited the answer.
              – Sparhawk
              Dec 7 at 8:07






            • 1




              @Kusalananda Thanks. Edited. Yeah, I interpreted the test in the question as looking for the current filename's suffix, rather than testing for a copy of the current file + .backup. It's a bit unclear, but if there were .foo, then .foo.backup were created, then .foo deleted, -f would result in .foo.backup.backup being created… which I assume is not preferred.
              – Sparhawk
              Dec 7 at 8:12










            • It’s not a bash script
              – justinnoor.io
              Dec 7 at 14:00










            • @justinnoor.io What do you mean? This is a bash script. Or are you saying that you do not want a bash script? Your shebang refers to /bin/sh, but depending on the system, this can be ambiguous. On my system (Arch Linux), if I change the shebang to /bin/sh, my script still works. It may well work on yours too.
              – Sparhawk
              Dec 7 at 23:08













            up vote
            1
            down vote










            up vote
            1
            down vote









            The test [ doesn't have enough information. You need to compare $file to a reference. You current construct says "if not this string", but you need to say "if x is not this string". I would use a regex, i.e. with [[ instead of [. Hence,



            #!/bin/bash
            GLOBIGNORE=.:..
            for file in .*; do
            if [[ ! "$file" =~ .backup$ ]]; then
            cp "$file" "$file.backup"
            fi
            done


            • As per Kusalananda's comment, I moved the shebang to /bin/bash, to ensure the [[ construct works.

            • As per Gordon Davisson's comment, I added the GLOBIGNORE, so that the script doesn't attempt to copy . and ..

            A few other things:




            • ./ in the paths is unnecessary. You are already in this directory!

            • I'm not sure if it was just a copy-paste issue, but you had instead of ".

            • Personally, I would just copy into another directory, and avoid all these issues, and avoid polluting my home directory. Actually, I would just (incrementally) backup everything instead!


            Here is a pure /bin/sh version. Instead of using the [[ bashism, I've used case instead.



            #!/bin/sh
            GLOBIGNORE=.:..
            for file in .*; do
            case "$file" in
            *.backup) ;;
            *) cp "$file" "$file.backup";;
            esac
            done





            share|improve this answer














            The test [ doesn't have enough information. You need to compare $file to a reference. You current construct says "if not this string", but you need to say "if x is not this string". I would use a regex, i.e. with [[ instead of [. Hence,



            #!/bin/bash
            GLOBIGNORE=.:..
            for file in .*; do
            if [[ ! "$file" =~ .backup$ ]]; then
            cp "$file" "$file.backup"
            fi
            done


            • As per Kusalananda's comment, I moved the shebang to /bin/bash, to ensure the [[ construct works.

            • As per Gordon Davisson's comment, I added the GLOBIGNORE, so that the script doesn't attempt to copy . and ..

            A few other things:




            • ./ in the paths is unnecessary. You are already in this directory!

            • I'm not sure if it was just a copy-paste issue, but you had instead of ".

            • Personally, I would just copy into another directory, and avoid all these issues, and avoid polluting my home directory. Actually, I would just (incrementally) backup everything instead!


            Here is a pure /bin/sh version. Instead of using the [[ bashism, I've used case instead.



            #!/bin/sh
            GLOBIGNORE=.:..
            for file in .*; do
            case "$file" in
            *.backup) ;;
            *) cp "$file" "$file.backup";;
            esac
            done






            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Dec 7 at 23:50

























            answered Dec 7 at 7:19









            Sparhawk

            9,13863890




            9,13863890







            • 1




              Also, this will try to back up . (the entire current directory) and .. (its parent), along with any dot directories (e.g. .ssh)... but fail because cp requires the -R option to do this.
              – Gordon Davisson
              Dec 7 at 7:29










            • @GordonDavisson Good point. I was actually testing with zsh, silly me. I've edited the answer.
              – Sparhawk
              Dec 7 at 8:07






            • 1




              @Kusalananda Thanks. Edited. Yeah, I interpreted the test in the question as looking for the current filename's suffix, rather than testing for a copy of the current file + .backup. It's a bit unclear, but if there were .foo, then .foo.backup were created, then .foo deleted, -f would result in .foo.backup.backup being created… which I assume is not preferred.
              – Sparhawk
              Dec 7 at 8:12










            • It’s not a bash script
              – justinnoor.io
              Dec 7 at 14:00










            • @justinnoor.io What do you mean? This is a bash script. Or are you saying that you do not want a bash script? Your shebang refers to /bin/sh, but depending on the system, this can be ambiguous. On my system (Arch Linux), if I change the shebang to /bin/sh, my script still works. It may well work on yours too.
              – Sparhawk
              Dec 7 at 23:08













            • 1




              Also, this will try to back up . (the entire current directory) and .. (its parent), along with any dot directories (e.g. .ssh)... but fail because cp requires the -R option to do this.
              – Gordon Davisson
              Dec 7 at 7:29










            • @GordonDavisson Good point. I was actually testing with zsh, silly me. I've edited the answer.
              – Sparhawk
              Dec 7 at 8:07






            • 1




              @Kusalananda Thanks. Edited. Yeah, I interpreted the test in the question as looking for the current filename's suffix, rather than testing for a copy of the current file + .backup. It's a bit unclear, but if there were .foo, then .foo.backup were created, then .foo deleted, -f would result in .foo.backup.backup being created… which I assume is not preferred.
              – Sparhawk
              Dec 7 at 8:12










            • It’s not a bash script
              – justinnoor.io
              Dec 7 at 14:00










            • @justinnoor.io What do you mean? This is a bash script. Or are you saying that you do not want a bash script? Your shebang refers to /bin/sh, but depending on the system, this can be ambiguous. On my system (Arch Linux), if I change the shebang to /bin/sh, my script still works. It may well work on yours too.
              – Sparhawk
              Dec 7 at 23:08








            1




            1




            Also, this will try to back up . (the entire current directory) and .. (its parent), along with any dot directories (e.g. .ssh)... but fail because cp requires the -R option to do this.
            – Gordon Davisson
            Dec 7 at 7:29




            Also, this will try to back up . (the entire current directory) and .. (its parent), along with any dot directories (e.g. .ssh)... but fail because cp requires the -R option to do this.
            – Gordon Davisson
            Dec 7 at 7:29












            @GordonDavisson Good point. I was actually testing with zsh, silly me. I've edited the answer.
            – Sparhawk
            Dec 7 at 8:07




            @GordonDavisson Good point. I was actually testing with zsh, silly me. I've edited the answer.
            – Sparhawk
            Dec 7 at 8:07




            1




            1




            @Kusalananda Thanks. Edited. Yeah, I interpreted the test in the question as looking for the current filename's suffix, rather than testing for a copy of the current file + .backup. It's a bit unclear, but if there were .foo, then .foo.backup were created, then .foo deleted, -f would result in .foo.backup.backup being created… which I assume is not preferred.
            – Sparhawk
            Dec 7 at 8:12




            @Kusalananda Thanks. Edited. Yeah, I interpreted the test in the question as looking for the current filename's suffix, rather than testing for a copy of the current file + .backup. It's a bit unclear, but if there were .foo, then .foo.backup were created, then .foo deleted, -f would result in .foo.backup.backup being created… which I assume is not preferred.
            – Sparhawk
            Dec 7 at 8:12












            It’s not a bash script
            – justinnoor.io
            Dec 7 at 14:00




            It’s not a bash script
            – justinnoor.io
            Dec 7 at 14:00












            @justinnoor.io What do you mean? This is a bash script. Or are you saying that you do not want a bash script? Your shebang refers to /bin/sh, but depending on the system, this can be ambiguous. On my system (Arch Linux), if I change the shebang to /bin/sh, my script still works. It may well work on yours too.
            – Sparhawk
            Dec 7 at 23:08





            @justinnoor.io What do you mean? This is a bash script. Or are you saying that you do not want a bash script? Your shebang refers to /bin/sh, but depending on the system, this can be ambiguous. On my system (Arch Linux), if I change the shebang to /bin/sh, my script still works. It may well work on yours too.
            – Sparhawk
            Dec 7 at 23:08











            up vote
            0
            down vote













            Why don't we simply use sed to backup?



            sed -i.bak 's#n#n#' <filepattern*>





            share|improve this answer
























              up vote
              0
              down vote













              Why don't we simply use sed to backup?



              sed -i.bak 's#n#n#' <filepattern*>





              share|improve this answer






















                up vote
                0
                down vote










                up vote
                0
                down vote









                Why don't we simply use sed to backup?



                sed -i.bak 's#n#n#' <filepattern*>





                share|improve this answer












                Why don't we simply use sed to backup?



                sed -i.bak 's#n#n#' <filepattern*>






                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Dec 7 at 7:44









                msp9011

                3,65543863




                3,65543863



























                    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.





                    Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


                    Please pay close attention to the following guidance:


                    • 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%2f486520%2fbacking-up-dotfiles-with-a-shell-script%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