Question - List files in a directory using -grep

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











up vote
0
down vote

favorite












The question wants me to list all the files stored in /usr/bin which the file names only contain lowercase English letters and contain the word 'file'.



For example, nsrfile and file should be in the output



Here's my code to achieve this



ls /usr/bin | grep '<[a-z]*file[a-z]*>'



and here's some part of the result I get.



file
nsrfile
grub2-file
systemd-tmpfiles


however, the question says that the file name should only contain lowercase English letters but not the slash -



and grub2-file even contains a number



how should I change my commands?







share|improve this question


























    up vote
    0
    down vote

    favorite












    The question wants me to list all the files stored in /usr/bin which the file names only contain lowercase English letters and contain the word 'file'.



    For example, nsrfile and file should be in the output



    Here's my code to achieve this



    ls /usr/bin | grep '<[a-z]*file[a-z]*>'



    and here's some part of the result I get.



    file
    nsrfile
    grub2-file
    systemd-tmpfiles


    however, the question says that the file name should only contain lowercase English letters but not the slash -



    and grub2-file even contains a number



    how should I change my commands?







    share|improve this question
























      up vote
      0
      down vote

      favorite









      up vote
      0
      down vote

      favorite











      The question wants me to list all the files stored in /usr/bin which the file names only contain lowercase English letters and contain the word 'file'.



      For example, nsrfile and file should be in the output



      Here's my code to achieve this



      ls /usr/bin | grep '<[a-z]*file[a-z]*>'



      and here's some part of the result I get.



      file
      nsrfile
      grub2-file
      systemd-tmpfiles


      however, the question says that the file name should only contain lowercase English letters but not the slash -



      and grub2-file even contains a number



      how should I change my commands?







      share|improve this question














      The question wants me to list all the files stored in /usr/bin which the file names only contain lowercase English letters and contain the word 'file'.



      For example, nsrfile and file should be in the output



      Here's my code to achieve this



      ls /usr/bin | grep '<[a-z]*file[a-z]*>'



      and here's some part of the result I get.



      file
      nsrfile
      grub2-file
      systemd-tmpfiles


      however, the question says that the file name should only contain lowercase English letters but not the slash -



      and grub2-file even contains a number



      how should I change my commands?









      share|improve this question













      share|improve this question




      share|improve this question








      edited Jan 31 at 22:34









      Isaac

      6,6371734




      6,6371734










      asked Jan 31 at 18:13









      Ulysses

      496




      496




















          4 Answers
          4






          active

          oldest

          votes

















          up vote
          0
          down vote



          accepted










          Expectation and warning



          Your assignment may expect you to grep the output of ls, perhaps something like this:



          cd /usr/bin
          ls | grep '^[a-z]*$' | xargs grep file


          Where you ask ls for the filenames, then have grep filter ones that start (^) and end ($) with only lower-case letters -- zero or more of them (*); you then ask xargs to grep each incoming filename for the string "file".



          This runs into immediate trouble as soon as any filenames (unlikely as these are to be in /usr/bin) contain a newline. (Files with spaces in them Some File Name will be excluded by the grep.) For a contrived example to show the point:



          cd ~/tmp/usr/bin
          touch a$'n'b
          ls | grep '^[a-z]*$' | xargs grep file
          grep: a: No such file or directory
          grep: b: No such file or directory


          In the above example, ls wrote the following contents to the pipe for grep:



          a
          b


          Grep rightfully passed both of those "filenames" down the pipe to xargs, which then thought it had two filenames to grep against, and so it ran:



          grep file a b


          ... which then complained about the missing files.



          Suggestion



          While it's not expectedd, I would suggest the following safer option, assuming a bash shell:



          shopt -s extglob
          grep -l file /usr/bin/!(*[^a-z]*)


          This turns on bash's extended globbing functionality. You then ask grep to list the filenames (-l) that contain the string "file" among the files in /usr/bin that do not (!) match the pattern: "anything (*) followed by any single ([ ... ]) non (^) -lower-case letter (a-z), followed by anything (*). In other words, only files that contain only lower-case letters in their name.






          share|improve this answer




















          • Thanks so much for those details. xargs would be the best thing I've learnt today
            – Ulysses
            Jan 31 at 20:02

















          up vote
          0
          down vote













          What I would do :



          printf '%sn' /usr/bin/* |
          grep '<[a-z]*file[a-z]*>' | grep -Ev '[0-9]|-'


          Explanation :



           grep -v


          is a reverse grep. There are two patterns: [0-9] and -






          share|improve this answer




















          • for your grep -Ev part. can I use '[^a-z]' because there might be other symbols
            – Ulysses
            Jan 31 at 18:24











          • | grep -Ev '[^a-z]'
            – Ulysses
            Jan 31 at 18:25


















          up vote
          0
          down vote













          You were close to the goal, just change the "word-boundary" (<>) limits to the start of line and end of line (^$) limits and all will be fine:



          $ ls /usr/bin | grep '^[a-z]*file[a-z]*$'
          file
          nsrfile


          That is: starting from the start of each line find lines that contain any amount of lowercase letters (a-z) zero or more times followed by the word file and lowercase letters again until the end of the line.



          Note that the above command will not work correctly for filenames with newlines.






          share|improve this answer



























            up vote
            0
            down vote













            Two solutions:



            A shell loop:



            for name in /usr/bin/*file*; do
            case "$name##*/" in
            *[!a-z]*) ;;
            *) printf '%sn' "$name"
            esac
            done


            This first generates a list of pathnames under /usr/bin whose basename matches *file* and then tests whether those basenames also contains characters that are not lowercase letters. If no non-lowercase letters are found, the pathname is printed.



            This would potentially also find names of directories that fulfil the criteria. If that is not wanted, just do



            [ ! -f "$name" ] && continue


            before the case statement to skip every name that is not a regular file.



            Using GNU find:



            find /usr/bin -maxdepth 1 -type f -name '*file*' -regex '.*/[a-z]*$'


            This also does a two stage filtering. First on the basename which must match *file*, and then on the end of the pathname (-regex matches against the complete pathname) to make sure there's only lowercase letters there.






            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: false,
              showLowRepImageUploadWarning: true,
              reputationToPostImages: null,
              bindNavPrevention: true,
              postfix: "",
              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%2f421032%2fquestion-list-files-in-a-directory-using-grep%23new-answer', 'question_page');

              );

              Post as a guest






























              4 Answers
              4






              active

              oldest

              votes








              4 Answers
              4






              active

              oldest

              votes









              active

              oldest

              votes






              active

              oldest

              votes








              up vote
              0
              down vote



              accepted










              Expectation and warning



              Your assignment may expect you to grep the output of ls, perhaps something like this:



              cd /usr/bin
              ls | grep '^[a-z]*$' | xargs grep file


              Where you ask ls for the filenames, then have grep filter ones that start (^) and end ($) with only lower-case letters -- zero or more of them (*); you then ask xargs to grep each incoming filename for the string "file".



              This runs into immediate trouble as soon as any filenames (unlikely as these are to be in /usr/bin) contain a newline. (Files with spaces in them Some File Name will be excluded by the grep.) For a contrived example to show the point:



              cd ~/tmp/usr/bin
              touch a$'n'b
              ls | grep '^[a-z]*$' | xargs grep file
              grep: a: No such file or directory
              grep: b: No such file or directory


              In the above example, ls wrote the following contents to the pipe for grep:



              a
              b


              Grep rightfully passed both of those "filenames" down the pipe to xargs, which then thought it had two filenames to grep against, and so it ran:



              grep file a b


              ... which then complained about the missing files.



              Suggestion



              While it's not expectedd, I would suggest the following safer option, assuming a bash shell:



              shopt -s extglob
              grep -l file /usr/bin/!(*[^a-z]*)


              This turns on bash's extended globbing functionality. You then ask grep to list the filenames (-l) that contain the string "file" among the files in /usr/bin that do not (!) match the pattern: "anything (*) followed by any single ([ ... ]) non (^) -lower-case letter (a-z), followed by anything (*). In other words, only files that contain only lower-case letters in their name.






              share|improve this answer




















              • Thanks so much for those details. xargs would be the best thing I've learnt today
                – Ulysses
                Jan 31 at 20:02














              up vote
              0
              down vote



              accepted










              Expectation and warning



              Your assignment may expect you to grep the output of ls, perhaps something like this:



              cd /usr/bin
              ls | grep '^[a-z]*$' | xargs grep file


              Where you ask ls for the filenames, then have grep filter ones that start (^) and end ($) with only lower-case letters -- zero or more of them (*); you then ask xargs to grep each incoming filename for the string "file".



              This runs into immediate trouble as soon as any filenames (unlikely as these are to be in /usr/bin) contain a newline. (Files with spaces in them Some File Name will be excluded by the grep.) For a contrived example to show the point:



              cd ~/tmp/usr/bin
              touch a$'n'b
              ls | grep '^[a-z]*$' | xargs grep file
              grep: a: No such file or directory
              grep: b: No such file or directory


              In the above example, ls wrote the following contents to the pipe for grep:



              a
              b


              Grep rightfully passed both of those "filenames" down the pipe to xargs, which then thought it had two filenames to grep against, and so it ran:



              grep file a b


              ... which then complained about the missing files.



              Suggestion



              While it's not expectedd, I would suggest the following safer option, assuming a bash shell:



              shopt -s extglob
              grep -l file /usr/bin/!(*[^a-z]*)


              This turns on bash's extended globbing functionality. You then ask grep to list the filenames (-l) that contain the string "file" among the files in /usr/bin that do not (!) match the pattern: "anything (*) followed by any single ([ ... ]) non (^) -lower-case letter (a-z), followed by anything (*). In other words, only files that contain only lower-case letters in their name.






              share|improve this answer




















              • Thanks so much for those details. xargs would be the best thing I've learnt today
                – Ulysses
                Jan 31 at 20:02












              up vote
              0
              down vote



              accepted







              up vote
              0
              down vote



              accepted






              Expectation and warning



              Your assignment may expect you to grep the output of ls, perhaps something like this:



              cd /usr/bin
              ls | grep '^[a-z]*$' | xargs grep file


              Where you ask ls for the filenames, then have grep filter ones that start (^) and end ($) with only lower-case letters -- zero or more of them (*); you then ask xargs to grep each incoming filename for the string "file".



              This runs into immediate trouble as soon as any filenames (unlikely as these are to be in /usr/bin) contain a newline. (Files with spaces in them Some File Name will be excluded by the grep.) For a contrived example to show the point:



              cd ~/tmp/usr/bin
              touch a$'n'b
              ls | grep '^[a-z]*$' | xargs grep file
              grep: a: No such file or directory
              grep: b: No such file or directory


              In the above example, ls wrote the following contents to the pipe for grep:



              a
              b


              Grep rightfully passed both of those "filenames" down the pipe to xargs, which then thought it had two filenames to grep against, and so it ran:



              grep file a b


              ... which then complained about the missing files.



              Suggestion



              While it's not expectedd, I would suggest the following safer option, assuming a bash shell:



              shopt -s extglob
              grep -l file /usr/bin/!(*[^a-z]*)


              This turns on bash's extended globbing functionality. You then ask grep to list the filenames (-l) that contain the string "file" among the files in /usr/bin that do not (!) match the pattern: "anything (*) followed by any single ([ ... ]) non (^) -lower-case letter (a-z), followed by anything (*). In other words, only files that contain only lower-case letters in their name.






              share|improve this answer












              Expectation and warning



              Your assignment may expect you to grep the output of ls, perhaps something like this:



              cd /usr/bin
              ls | grep '^[a-z]*$' | xargs grep file


              Where you ask ls for the filenames, then have grep filter ones that start (^) and end ($) with only lower-case letters -- zero or more of them (*); you then ask xargs to grep each incoming filename for the string "file".



              This runs into immediate trouble as soon as any filenames (unlikely as these are to be in /usr/bin) contain a newline. (Files with spaces in them Some File Name will be excluded by the grep.) For a contrived example to show the point:



              cd ~/tmp/usr/bin
              touch a$'n'b
              ls | grep '^[a-z]*$' | xargs grep file
              grep: a: No such file or directory
              grep: b: No such file or directory


              In the above example, ls wrote the following contents to the pipe for grep:



              a
              b


              Grep rightfully passed both of those "filenames" down the pipe to xargs, which then thought it had two filenames to grep against, and so it ran:



              grep file a b


              ... which then complained about the missing files.



              Suggestion



              While it's not expectedd, I would suggest the following safer option, assuming a bash shell:



              shopt -s extglob
              grep -l file /usr/bin/!(*[^a-z]*)


              This turns on bash's extended globbing functionality. You then ask grep to list the filenames (-l) that contain the string "file" among the files in /usr/bin that do not (!) match the pattern: "anything (*) followed by any single ([ ... ]) non (^) -lower-case letter (a-z), followed by anything (*). In other words, only files that contain only lower-case letters in their name.







              share|improve this answer












              share|improve this answer



              share|improve this answer










              answered Jan 31 at 18:45









              Jeff Schaller

              31.4k846105




              31.4k846105











              • Thanks so much for those details. xargs would be the best thing I've learnt today
                – Ulysses
                Jan 31 at 20:02
















              • Thanks so much for those details. xargs would be the best thing I've learnt today
                – Ulysses
                Jan 31 at 20:02















              Thanks so much for those details. xargs would be the best thing I've learnt today
              – Ulysses
              Jan 31 at 20:02




              Thanks so much for those details. xargs would be the best thing I've learnt today
              – Ulysses
              Jan 31 at 20:02












              up vote
              0
              down vote













              What I would do :



              printf '%sn' /usr/bin/* |
              grep '<[a-z]*file[a-z]*>' | grep -Ev '[0-9]|-'


              Explanation :



               grep -v


              is a reverse grep. There are two patterns: [0-9] and -






              share|improve this answer




















              • for your grep -Ev part. can I use '[^a-z]' because there might be other symbols
                – Ulysses
                Jan 31 at 18:24











              • | grep -Ev '[^a-z]'
                – Ulysses
                Jan 31 at 18:25















              up vote
              0
              down vote













              What I would do :



              printf '%sn' /usr/bin/* |
              grep '<[a-z]*file[a-z]*>' | grep -Ev '[0-9]|-'


              Explanation :



               grep -v


              is a reverse grep. There are two patterns: [0-9] and -






              share|improve this answer




















              • for your grep -Ev part. can I use '[^a-z]' because there might be other symbols
                – Ulysses
                Jan 31 at 18:24











              • | grep -Ev '[^a-z]'
                – Ulysses
                Jan 31 at 18:25













              up vote
              0
              down vote










              up vote
              0
              down vote









              What I would do :



              printf '%sn' /usr/bin/* |
              grep '<[a-z]*file[a-z]*>' | grep -Ev '[0-9]|-'


              Explanation :



               grep -v


              is a reverse grep. There are two patterns: [0-9] and -






              share|improve this answer












              What I would do :



              printf '%sn' /usr/bin/* |
              grep '<[a-z]*file[a-z]*>' | grep -Ev '[0-9]|-'


              Explanation :



               grep -v


              is a reverse grep. There are two patterns: [0-9] and -







              share|improve this answer












              share|improve this answer



              share|improve this answer










              answered Jan 31 at 18:19









              Gilles Quenot

              15.3k13448




              15.3k13448











              • for your grep -Ev part. can I use '[^a-z]' because there might be other symbols
                – Ulysses
                Jan 31 at 18:24











              • | grep -Ev '[^a-z]'
                – Ulysses
                Jan 31 at 18:25

















              • for your grep -Ev part. can I use '[^a-z]' because there might be other symbols
                – Ulysses
                Jan 31 at 18:24











              • | grep -Ev '[^a-z]'
                – Ulysses
                Jan 31 at 18:25
















              for your grep -Ev part. can I use '[^a-z]' because there might be other symbols
              – Ulysses
              Jan 31 at 18:24





              for your grep -Ev part. can I use '[^a-z]' because there might be other symbols
              – Ulysses
              Jan 31 at 18:24













              | grep -Ev '[^a-z]'
              – Ulysses
              Jan 31 at 18:25





              | grep -Ev '[^a-z]'
              – Ulysses
              Jan 31 at 18:25











              up vote
              0
              down vote













              You were close to the goal, just change the "word-boundary" (<>) limits to the start of line and end of line (^$) limits and all will be fine:



              $ ls /usr/bin | grep '^[a-z]*file[a-z]*$'
              file
              nsrfile


              That is: starting from the start of each line find lines that contain any amount of lowercase letters (a-z) zero or more times followed by the word file and lowercase letters again until the end of the line.



              Note that the above command will not work correctly for filenames with newlines.






              share|improve this answer
























                up vote
                0
                down vote













                You were close to the goal, just change the "word-boundary" (<>) limits to the start of line and end of line (^$) limits and all will be fine:



                $ ls /usr/bin | grep '^[a-z]*file[a-z]*$'
                file
                nsrfile


                That is: starting from the start of each line find lines that contain any amount of lowercase letters (a-z) zero or more times followed by the word file and lowercase letters again until the end of the line.



                Note that the above command will not work correctly for filenames with newlines.






                share|improve this answer






















                  up vote
                  0
                  down vote










                  up vote
                  0
                  down vote









                  You were close to the goal, just change the "word-boundary" (<>) limits to the start of line and end of line (^$) limits and all will be fine:



                  $ ls /usr/bin | grep '^[a-z]*file[a-z]*$'
                  file
                  nsrfile


                  That is: starting from the start of each line find lines that contain any amount of lowercase letters (a-z) zero or more times followed by the word file and lowercase letters again until the end of the line.



                  Note that the above command will not work correctly for filenames with newlines.






                  share|improve this answer












                  You were close to the goal, just change the "word-boundary" (<>) limits to the start of line and end of line (^$) limits and all will be fine:



                  $ ls /usr/bin | grep '^[a-z]*file[a-z]*$'
                  file
                  nsrfile


                  That is: starting from the start of each line find lines that contain any amount of lowercase letters (a-z) zero or more times followed by the word file and lowercase letters again until the end of the line.



                  Note that the above command will not work correctly for filenames with newlines.







                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Jan 31 at 22:47









                  Isaac

                  6,6371734




                  6,6371734




















                      up vote
                      0
                      down vote













                      Two solutions:



                      A shell loop:



                      for name in /usr/bin/*file*; do
                      case "$name##*/" in
                      *[!a-z]*) ;;
                      *) printf '%sn' "$name"
                      esac
                      done


                      This first generates a list of pathnames under /usr/bin whose basename matches *file* and then tests whether those basenames also contains characters that are not lowercase letters. If no non-lowercase letters are found, the pathname is printed.



                      This would potentially also find names of directories that fulfil the criteria. If that is not wanted, just do



                      [ ! -f "$name" ] && continue


                      before the case statement to skip every name that is not a regular file.



                      Using GNU find:



                      find /usr/bin -maxdepth 1 -type f -name '*file*' -regex '.*/[a-z]*$'


                      This also does a two stage filtering. First on the basename which must match *file*, and then on the end of the pathname (-regex matches against the complete pathname) to make sure there's only lowercase letters there.






                      share|improve this answer
























                        up vote
                        0
                        down vote













                        Two solutions:



                        A shell loop:



                        for name in /usr/bin/*file*; do
                        case "$name##*/" in
                        *[!a-z]*) ;;
                        *) printf '%sn' "$name"
                        esac
                        done


                        This first generates a list of pathnames under /usr/bin whose basename matches *file* and then tests whether those basenames also contains characters that are not lowercase letters. If no non-lowercase letters are found, the pathname is printed.



                        This would potentially also find names of directories that fulfil the criteria. If that is not wanted, just do



                        [ ! -f "$name" ] && continue


                        before the case statement to skip every name that is not a regular file.



                        Using GNU find:



                        find /usr/bin -maxdepth 1 -type f -name '*file*' -regex '.*/[a-z]*$'


                        This also does a two stage filtering. First on the basename which must match *file*, and then on the end of the pathname (-regex matches against the complete pathname) to make sure there's only lowercase letters there.






                        share|improve this answer






















                          up vote
                          0
                          down vote










                          up vote
                          0
                          down vote









                          Two solutions:



                          A shell loop:



                          for name in /usr/bin/*file*; do
                          case "$name##*/" in
                          *[!a-z]*) ;;
                          *) printf '%sn' "$name"
                          esac
                          done


                          This first generates a list of pathnames under /usr/bin whose basename matches *file* and then tests whether those basenames also contains characters that are not lowercase letters. If no non-lowercase letters are found, the pathname is printed.



                          This would potentially also find names of directories that fulfil the criteria. If that is not wanted, just do



                          [ ! -f "$name" ] && continue


                          before the case statement to skip every name that is not a regular file.



                          Using GNU find:



                          find /usr/bin -maxdepth 1 -type f -name '*file*' -regex '.*/[a-z]*$'


                          This also does a two stage filtering. First on the basename which must match *file*, and then on the end of the pathname (-regex matches against the complete pathname) to make sure there's only lowercase letters there.






                          share|improve this answer












                          Two solutions:



                          A shell loop:



                          for name in /usr/bin/*file*; do
                          case "$name##*/" in
                          *[!a-z]*) ;;
                          *) printf '%sn' "$name"
                          esac
                          done


                          This first generates a list of pathnames under /usr/bin whose basename matches *file* and then tests whether those basenames also contains characters that are not lowercase letters. If no non-lowercase letters are found, the pathname is printed.



                          This would potentially also find names of directories that fulfil the criteria. If that is not wanted, just do



                          [ ! -f "$name" ] && continue


                          before the case statement to skip every name that is not a regular file.



                          Using GNU find:



                          find /usr/bin -maxdepth 1 -type f -name '*file*' -regex '.*/[a-z]*$'


                          This also does a two stage filtering. First on the basename which must match *file*, and then on the end of the pathname (-regex matches against the complete pathname) to make sure there's only lowercase letters there.







                          share|improve this answer












                          share|improve this answer



                          share|improve this answer










                          answered May 20 at 15:45









                          Kusalananda

                          103k13202318




                          103k13202318






















                               

                              draft saved


                              draft discarded


























                               


                              draft saved


                              draft discarded














                              StackExchange.ready(
                              function ()
                              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f421032%2fquestion-list-files-in-a-directory-using-grep%23new-answer', 'question_page');

                              );

                              Post as a guest













































































                              Popular posts from this blog

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

                              Displaying single band from multi-band raster using QGIS

                              How many registers does an x86_64 CPU actually have?