Freebsd: backing up dotfiles with a shell script












0














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





























    0














    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



























      0












      0








      0







      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 freebsd






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited yesterday

























      asked Dec 7 at 6:57









      justinnoor.io

      348218




      348218






















          3 Answers
          3






          active

          oldest

          votes


















          1














          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



















          1














          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





















          0














          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',
            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%2f486520%2ffreebsd-backing-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









            1














            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
















            1














            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














            1












            1








            1






            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













            1














            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


















            1














            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
















            1












            1








            1






            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,20863890




            9,20863890








            • 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













            0














            Why don't we simply use sed to backup?



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





            share|improve this answer


























              0














              Why don't we simply use sed to backup?



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





              share|improve this answer
























                0












                0








                0






                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%2ffreebsd-backing-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

                    Entries order in /etc/network/interfaces

                    新発田市

                    Grub takes very long (several minutes) to open Menu (in Multi-Boot-System)