Use read line to iterate over variables











up vote
3
down vote

favorite












I have the following files:



$ ls *.png | egrep -i "am|pm"
output-0 11.42.30 AM.png
output-0 5.10.12 PM.png
....


I want to remove them but get this error:



$ ls *.png | egrep -i "am|pm" | while read line; do rm "$line"; done
rm: cannot remove ''$'33''[0m'$'33''[01;35moutput-0 11.42.30 AM.png'$'33''[0m': No such file or directory
rm: cannot remove ''$'33''[01;35moutput-0 5.10.12 PM.png'$'33''[0m': No such file or directory
rm: cannot remove ''$'33''[01;35moutput-1 11.42.30 AM.png'$'33''[0m': No such file or directory


What's the problem with my codes?










share|improve this question




















  • 3




    I suspect ls is aliased to ls --color=always instead of ...=auto. Try ls ... to run the actual ls command and not some alias.
    – PerlDuck
    Dec 2 at 10:33






  • 4




    Please also see Why not parse ls (and what do to instead)?
    – Byte Commander
    Dec 2 at 16:03






  • 3




    and Bash pitfalls: for f in $(ls *.mp3) and Why you shouldn't parse the output of ls
    – Byte Commander
    Dec 2 at 16:08















up vote
3
down vote

favorite












I have the following files:



$ ls *.png | egrep -i "am|pm"
output-0 11.42.30 AM.png
output-0 5.10.12 PM.png
....


I want to remove them but get this error:



$ ls *.png | egrep -i "am|pm" | while read line; do rm "$line"; done
rm: cannot remove ''$'33''[0m'$'33''[01;35moutput-0 11.42.30 AM.png'$'33''[0m': No such file or directory
rm: cannot remove ''$'33''[01;35moutput-0 5.10.12 PM.png'$'33''[0m': No such file or directory
rm: cannot remove ''$'33''[01;35moutput-1 11.42.30 AM.png'$'33''[0m': No such file or directory


What's the problem with my codes?










share|improve this question




















  • 3




    I suspect ls is aliased to ls --color=always instead of ...=auto. Try ls ... to run the actual ls command and not some alias.
    – PerlDuck
    Dec 2 at 10:33






  • 4




    Please also see Why not parse ls (and what do to instead)?
    – Byte Commander
    Dec 2 at 16:03






  • 3




    and Bash pitfalls: for f in $(ls *.mp3) and Why you shouldn't parse the output of ls
    – Byte Commander
    Dec 2 at 16:08













up vote
3
down vote

favorite









up vote
3
down vote

favorite











I have the following files:



$ ls *.png | egrep -i "am|pm"
output-0 11.42.30 AM.png
output-0 5.10.12 PM.png
....


I want to remove them but get this error:



$ ls *.png | egrep -i "am|pm" | while read line; do rm "$line"; done
rm: cannot remove ''$'33''[0m'$'33''[01;35moutput-0 11.42.30 AM.png'$'33''[0m': No such file or directory
rm: cannot remove ''$'33''[01;35moutput-0 5.10.12 PM.png'$'33''[0m': No such file or directory
rm: cannot remove ''$'33''[01;35moutput-1 11.42.30 AM.png'$'33''[0m': No such file or directory


What's the problem with my codes?










share|improve this question















I have the following files:



$ ls *.png | egrep -i "am|pm"
output-0 11.42.30 AM.png
output-0 5.10.12 PM.png
....


I want to remove them but get this error:



$ ls *.png | egrep -i "am|pm" | while read line; do rm "$line"; done
rm: cannot remove ''$'33''[0m'$'33''[01;35moutput-0 11.42.30 AM.png'$'33''[0m': No such file or directory
rm: cannot remove ''$'33''[01;35moutput-0 5.10.12 PM.png'$'33''[0m': No such file or directory
rm: cannot remove ''$'33''[01;35moutput-1 11.42.30 AM.png'$'33''[0m': No such file or directory


What's the problem with my codes?







command-line bash ls






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Dec 2 at 16:02









Byte Commander

62.6k26169285




62.6k26169285










asked Dec 2 at 10:23









user10726006

473




473








  • 3




    I suspect ls is aliased to ls --color=always instead of ...=auto. Try ls ... to run the actual ls command and not some alias.
    – PerlDuck
    Dec 2 at 10:33






  • 4




    Please also see Why not parse ls (and what do to instead)?
    – Byte Commander
    Dec 2 at 16:03






  • 3




    and Bash pitfalls: for f in $(ls *.mp3) and Why you shouldn't parse the output of ls
    – Byte Commander
    Dec 2 at 16:08














  • 3




    I suspect ls is aliased to ls --color=always instead of ...=auto. Try ls ... to run the actual ls command and not some alias.
    – PerlDuck
    Dec 2 at 10:33






  • 4




    Please also see Why not parse ls (and what do to instead)?
    – Byte Commander
    Dec 2 at 16:03






  • 3




    and Bash pitfalls: for f in $(ls *.mp3) and Why you shouldn't parse the output of ls
    – Byte Commander
    Dec 2 at 16:08








3




3




I suspect ls is aliased to ls --color=always instead of ...=auto. Try ls ... to run the actual ls command and not some alias.
– PerlDuck
Dec 2 at 10:33




I suspect ls is aliased to ls --color=always instead of ...=auto. Try ls ... to run the actual ls command and not some alias.
– PerlDuck
Dec 2 at 10:33




4




4




Please also see Why not parse ls (and what do to instead)?
– Byte Commander
Dec 2 at 16:03




Please also see Why not parse ls (and what do to instead)?
– Byte Commander
Dec 2 at 16:03




3




3




and Bash pitfalls: for f in $(ls *.mp3) and Why you shouldn't parse the output of ls
– Byte Commander
Dec 2 at 16:08




and Bash pitfalls: for f in $(ls *.mp3) and Why you shouldn't parse the output of ls
– Byte Commander
Dec 2 at 16:08










2 Answers
2






active

oldest

votes

















up vote
9
down vote



accepted










ls is risky in scripts and command lines. One problem is what is described in a comment by @PerlDuck, ANSI escape sequences for colour output. I would recommend another approach with find





  • Create test files



    touch 'output-0 11.42.30 AM.png' 'output-0 5.10.12 PM.png' asdf.png



  • Check that the findcommand line finds the files that you expect it to find



    find . -type f -iname "*[ap]m*.png"


    and do it



    find . -type f -iname "*[ap]m*.png" -delete


    If you don't want to search into subdirectories, add -maxdepth 1



    find . -maxdepth 1 -type f -iname "*[ap]m*.png" -delete



  • Check the result



    ls


    Files with am, pm, AM, PM in the name should be deleted but asdf.png is not deleted.








share|improve this answer






























    up vote
    6
    down vote













    If you really want to use a while read loop in that way, then use a shell glob and printf with null delimiters e.g.



    printf '%s' *.png | grep -zEi 'am|pm' | while IFS= read -r -d '' line; do echo "$line"; done


    However, there are several ways to get bash to expand to a list of the files to be deleted directly - without the need to pipe to grep and while:





    1. using simple shell globs



      rm -- *[ap]m.png *[AP]M.png


      or - if you don't mind matching a .PNG extension as well - making use of the nocaseglob option



      shopt -s nocaseglob
      rm -- *[ap]m.png



    2. using extended globs



      shopt -s extglob
      rm -- *@(AM|PM).png *@(am|pm).png



    or



        shopt -s extglob nocaseglob
    rm -- *@(am|pm).png


    The -- marks the end of options, just in case there are filenames that begin with a hyphen - you can use a pattern with an explicit directory prefix like ./*(am|pm) instead if you prefer.



    Add the -i or -I option if you want to review the file names interactively before deletion.






    share|improve this answer























      Your Answer








      StackExchange.ready(function() {
      var channelOptions = {
      tags: "".split(" "),
      id: "89"
      };
      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: 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%2faskubuntu.com%2fquestions%2f1097863%2fuse-read-line-to-iterate-over-variables%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








      up vote
      9
      down vote



      accepted










      ls is risky in scripts and command lines. One problem is what is described in a comment by @PerlDuck, ANSI escape sequences for colour output. I would recommend another approach with find





      • Create test files



        touch 'output-0 11.42.30 AM.png' 'output-0 5.10.12 PM.png' asdf.png



      • Check that the findcommand line finds the files that you expect it to find



        find . -type f -iname "*[ap]m*.png"


        and do it



        find . -type f -iname "*[ap]m*.png" -delete


        If you don't want to search into subdirectories, add -maxdepth 1



        find . -maxdepth 1 -type f -iname "*[ap]m*.png" -delete



      • Check the result



        ls


        Files with am, pm, AM, PM in the name should be deleted but asdf.png is not deleted.








      share|improve this answer



























        up vote
        9
        down vote



        accepted










        ls is risky in scripts and command lines. One problem is what is described in a comment by @PerlDuck, ANSI escape sequences for colour output. I would recommend another approach with find





        • Create test files



          touch 'output-0 11.42.30 AM.png' 'output-0 5.10.12 PM.png' asdf.png



        • Check that the findcommand line finds the files that you expect it to find



          find . -type f -iname "*[ap]m*.png"


          and do it



          find . -type f -iname "*[ap]m*.png" -delete


          If you don't want to search into subdirectories, add -maxdepth 1



          find . -maxdepth 1 -type f -iname "*[ap]m*.png" -delete



        • Check the result



          ls


          Files with am, pm, AM, PM in the name should be deleted but asdf.png is not deleted.








        share|improve this answer

























          up vote
          9
          down vote



          accepted







          up vote
          9
          down vote



          accepted






          ls is risky in scripts and command lines. One problem is what is described in a comment by @PerlDuck, ANSI escape sequences for colour output. I would recommend another approach with find





          • Create test files



            touch 'output-0 11.42.30 AM.png' 'output-0 5.10.12 PM.png' asdf.png



          • Check that the findcommand line finds the files that you expect it to find



            find . -type f -iname "*[ap]m*.png"


            and do it



            find . -type f -iname "*[ap]m*.png" -delete


            If you don't want to search into subdirectories, add -maxdepth 1



            find . -maxdepth 1 -type f -iname "*[ap]m*.png" -delete



          • Check the result



            ls


            Files with am, pm, AM, PM in the name should be deleted but asdf.png is not deleted.








          share|improve this answer














          ls is risky in scripts and command lines. One problem is what is described in a comment by @PerlDuck, ANSI escape sequences for colour output. I would recommend another approach with find





          • Create test files



            touch 'output-0 11.42.30 AM.png' 'output-0 5.10.12 PM.png' asdf.png



          • Check that the findcommand line finds the files that you expect it to find



            find . -type f -iname "*[ap]m*.png"


            and do it



            find . -type f -iname "*[ap]m*.png" -delete


            If you don't want to search into subdirectories, add -maxdepth 1



            find . -maxdepth 1 -type f -iname "*[ap]m*.png" -delete



          • Check the result



            ls


            Files with am, pm, AM, PM in the name should be deleted but asdf.png is not deleted.









          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Dec 2 at 15:51

























          answered Dec 2 at 10:58









          sudodus

          22.4k32872




          22.4k32872
























              up vote
              6
              down vote













              If you really want to use a while read loop in that way, then use a shell glob and printf with null delimiters e.g.



              printf '%s' *.png | grep -zEi 'am|pm' | while IFS= read -r -d '' line; do echo "$line"; done


              However, there are several ways to get bash to expand to a list of the files to be deleted directly - without the need to pipe to grep and while:





              1. using simple shell globs



                rm -- *[ap]m.png *[AP]M.png


                or - if you don't mind matching a .PNG extension as well - making use of the nocaseglob option



                shopt -s nocaseglob
                rm -- *[ap]m.png



              2. using extended globs



                shopt -s extglob
                rm -- *@(AM|PM).png *@(am|pm).png



              or



                  shopt -s extglob nocaseglob
              rm -- *@(am|pm).png


              The -- marks the end of options, just in case there are filenames that begin with a hyphen - you can use a pattern with an explicit directory prefix like ./*(am|pm) instead if you prefer.



              Add the -i or -I option if you want to review the file names interactively before deletion.






              share|improve this answer



























                up vote
                6
                down vote













                If you really want to use a while read loop in that way, then use a shell glob and printf with null delimiters e.g.



                printf '%s' *.png | grep -zEi 'am|pm' | while IFS= read -r -d '' line; do echo "$line"; done


                However, there are several ways to get bash to expand to a list of the files to be deleted directly - without the need to pipe to grep and while:





                1. using simple shell globs



                  rm -- *[ap]m.png *[AP]M.png


                  or - if you don't mind matching a .PNG extension as well - making use of the nocaseglob option



                  shopt -s nocaseglob
                  rm -- *[ap]m.png



                2. using extended globs



                  shopt -s extglob
                  rm -- *@(AM|PM).png *@(am|pm).png



                or



                    shopt -s extglob nocaseglob
                rm -- *@(am|pm).png


                The -- marks the end of options, just in case there are filenames that begin with a hyphen - you can use a pattern with an explicit directory prefix like ./*(am|pm) instead if you prefer.



                Add the -i or -I option if you want to review the file names interactively before deletion.






                share|improve this answer

























                  up vote
                  6
                  down vote










                  up vote
                  6
                  down vote









                  If you really want to use a while read loop in that way, then use a shell glob and printf with null delimiters e.g.



                  printf '%s' *.png | grep -zEi 'am|pm' | while IFS= read -r -d '' line; do echo "$line"; done


                  However, there are several ways to get bash to expand to a list of the files to be deleted directly - without the need to pipe to grep and while:





                  1. using simple shell globs



                    rm -- *[ap]m.png *[AP]M.png


                    or - if you don't mind matching a .PNG extension as well - making use of the nocaseglob option



                    shopt -s nocaseglob
                    rm -- *[ap]m.png



                  2. using extended globs



                    shopt -s extglob
                    rm -- *@(AM|PM).png *@(am|pm).png



                  or



                      shopt -s extglob nocaseglob
                  rm -- *@(am|pm).png


                  The -- marks the end of options, just in case there are filenames that begin with a hyphen - you can use a pattern with an explicit directory prefix like ./*(am|pm) instead if you prefer.



                  Add the -i or -I option if you want to review the file names interactively before deletion.






                  share|improve this answer














                  If you really want to use a while read loop in that way, then use a shell glob and printf with null delimiters e.g.



                  printf '%s' *.png | grep -zEi 'am|pm' | while IFS= read -r -d '' line; do echo "$line"; done


                  However, there are several ways to get bash to expand to a list of the files to be deleted directly - without the need to pipe to grep and while:





                  1. using simple shell globs



                    rm -- *[ap]m.png *[AP]M.png


                    or - if you don't mind matching a .PNG extension as well - making use of the nocaseglob option



                    shopt -s nocaseglob
                    rm -- *[ap]m.png



                  2. using extended globs



                    shopt -s extglob
                    rm -- *@(AM|PM).png *@(am|pm).png



                  or



                      shopt -s extglob nocaseglob
                  rm -- *@(am|pm).png


                  The -- marks the end of options, just in case there are filenames that begin with a hyphen - you can use a pattern with an explicit directory prefix like ./*(am|pm) instead if you prefer.



                  Add the -i or -I option if you want to review the file names interactively before deletion.







                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited Dec 2 at 16:22

























                  answered Dec 2 at 13:27









                  steeldriver

                  65.3k11104176




                  65.3k11104176






























                      draft saved

                      draft discarded




















































                      Thanks for contributing an answer to Ask Ubuntu!


                      • 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%2faskubuntu.com%2fquestions%2f1097863%2fuse-read-line-to-iterate-over-variables%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

                      Quarter-circle Tiles

                      build a pushdown automaton that recognizes the reverse language of a given pushdown automaton?

                      Mont Emei