Find command that excludes paths listed in a file

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











up vote
2
down vote

favorite












I need to exclude a bunch of paths from a find command. For example:



find "$(pwd)" -not ( 
-path "*/.git"
-o -path "*/.git/*"
-o -path "*/.vscode"
-o -path "*/.vscode/*"
-o -path "*/node_modules"
-o -path "*/node_modules/*"
-o -path "*/Image"
-o -path "*/Image/*"
-o -path "*/Rendered"
-o -path "*/Rendered/*"
-o -path "*/iNotebook"
-o -path "*/iNotebook/*"
-o -path "*/GeneratedTest"
-o -path "*/GeneratedTest/*"
-o -path "*/GeneratedOutput"
-o -path "*/GeneratedOutput/*"
-o -path "*/*_files" ) -type d


However, I want to read these paths from a text file instead of listing them all on the command-line. How can I do that?










share|improve this question



























    up vote
    2
    down vote

    favorite












    I need to exclude a bunch of paths from a find command. For example:



    find "$(pwd)" -not ( 
    -path "*/.git"
    -o -path "*/.git/*"
    -o -path "*/.vscode"
    -o -path "*/.vscode/*"
    -o -path "*/node_modules"
    -o -path "*/node_modules/*"
    -o -path "*/Image"
    -o -path "*/Image/*"
    -o -path "*/Rendered"
    -o -path "*/Rendered/*"
    -o -path "*/iNotebook"
    -o -path "*/iNotebook/*"
    -o -path "*/GeneratedTest"
    -o -path "*/GeneratedTest/*"
    -o -path "*/GeneratedOutput"
    -o -path "*/GeneratedOutput/*"
    -o -path "*/*_files" ) -type d


    However, I want to read these paths from a text file instead of listing them all on the command-line. How can I do that?










    share|improve this question

























      up vote
      2
      down vote

      favorite









      up vote
      2
      down vote

      favorite











      I need to exclude a bunch of paths from a find command. For example:



      find "$(pwd)" -not ( 
      -path "*/.git"
      -o -path "*/.git/*"
      -o -path "*/.vscode"
      -o -path "*/.vscode/*"
      -o -path "*/node_modules"
      -o -path "*/node_modules/*"
      -o -path "*/Image"
      -o -path "*/Image/*"
      -o -path "*/Rendered"
      -o -path "*/Rendered/*"
      -o -path "*/iNotebook"
      -o -path "*/iNotebook/*"
      -o -path "*/GeneratedTest"
      -o -path "*/GeneratedTest/*"
      -o -path "*/GeneratedOutput"
      -o -path "*/GeneratedOutput/*"
      -o -path "*/*_files" ) -type d


      However, I want to read these paths from a text file instead of listing them all on the command-line. How can I do that?










      share|improve this question















      I need to exclude a bunch of paths from a find command. For example:



      find "$(pwd)" -not ( 
      -path "*/.git"
      -o -path "*/.git/*"
      -o -path "*/.vscode"
      -o -path "*/.vscode/*"
      -o -path "*/node_modules"
      -o -path "*/node_modules/*"
      -o -path "*/Image"
      -o -path "*/Image/*"
      -o -path "*/Rendered"
      -o -path "*/Rendered/*"
      -o -path "*/iNotebook"
      -o -path "*/iNotebook/*"
      -o -path "*/GeneratedTest"
      -o -path "*/GeneratedTest/*"
      -o -path "*/GeneratedOutput"
      -o -path "*/GeneratedOutput/*"
      -o -path "*/*_files" ) -type d


      However, I want to read these paths from a text file instead of listing them all on the command-line. How can I do that?







      bash find path xargs gnu






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Sep 13 at 18:13









      Michael Mrozek♦

      58.8k27184207




      58.8k27184207










      asked Sep 13 at 7:45









      Nikhil

      1799




      1799




















          3 Answers
          3






          active

          oldest

          votes

















          up vote
          3
          down vote



          accepted










          Construct an array that you later use in your call to find. The following script reads the newline-delimited path patterns from its standard input and calls find:



          #!/bin/sh

          set --

          while IFS= read -r path; do
          set -- "$@" -o -path "$path"
          done

          shift # remove initial "-o" from $@

          find . -type d ! '(' "$@" ')'


          You would run this with



          ./script.sh <paths.txt


          where paths.txt might look like



          */.git
          */.git/*
          */.vscode
          */.vscode/*
          */node_modules
          */node_modules/*
          */Image
          */Image/*
          */Rendered
          */Rendered/*
          */iNotebook
          */iNotebook/*
          */GeneratedTest
          */GeneratedTest/*
          */GeneratedOutput
          */GeneratedOutput/*
          */*_files


          Or, since your path patterns are all basically names of directories:



          #!/bin/sh

          set --

          while IFS= read -r dirname; do
          set -- "$@" -o '(' -name "$dirname" -prune ')'
          done

          shift # remove initial "-o" from $@

          find . -type d ! '(' "$@" ')'


          with the pattern file containing



          .git
          .vscode
          node_modules
          Image
          Rendered
          iNotebook
          GeneratedTest
          GeneratedOutput
          *_files


          This variant of the code would stop find from even descending into the directories matching the patterns in the file, whereas the first script (as well as your code) would test the -path patterns against everything in the excluded directories regardless of the fact that you're not interested in anything below those paths.






          share|improve this answer





























            up vote
            2
            down vote













            You can use grep and find’s -exec to filter files against a list of paths, either as regular expressions or fixed strings. Adapting your example, create a file named paths containing



            /.git$
            /.git/
            /.vscode$
            /.vscode/
            /node_modules$
            /node_modules/
            /Image$
            /Image/
            /Rendered$
            /Rendered/
            /iNotebook$
            /iNotebook/
            /GeneratedTest$
            /GeneratedTest/
            /GeneratedOutput$
            /GeneratedOutput/
            /.*_files$


            Then run



            find /your/search/path -type d ! -exec sh -c "echo | grep -q -f paths" ; -print


            This looks for directories under /your/search/path, and for each one it finds, uses grep to determine whether it matches a pattern in paths; if it doesn’t, it prints it. This is intended as a base for extension; if you only care about the paths of directories which don’t match the patterns in a file, and none of the paths cover multiple lines, you can post-process the output using a single grep invocation:



            find /your/search/path -type d | grep -v -f paths


            If you’re really not interested in certain paths at all (i.e. your patterns always match a directory name and then everything under that directory), you could make things simpler by pruning:



            find /your/search/path -type d ( -exec sh -c "echo | grep -q -f paths" ; -prune -o -print )


            with the following contents in paths:



            /.git$
            /.vscode$
            /node_modules$
            /Image$
            /Rendered$
            /iNotebook$
            /GeneratedTest$
            /GeneratedOutput$
            /.*_files$





            share|improve this answer



























              up vote
              1
              down vote













              What can be done is to built up the command using awk and pass it to find as variable in a "wrapper" script or shell function



              p=$( awk 'printf "-not -path %s ",$0' "$1" )
              find "$PWD" $p -type d


              And call it as ./find_wrapper.sh paths.txt, where path.txt is the list of quoted paths.



              '*/.git'
              '*/.git/*'
              '*/.vscode'
              '*/.vscode/*'
              '*/node_modules'
              '*/node_modules/*'
              '*/Image'
              ...


              Why it's done this way ? The reason awk builts a one whole line is because there's no reason to do that in script - the line continuations are for making the command look more organized, but functionally it doesn't give any advantage. $p is unquoted, since we actually want word splitting here. Otherwise find sees it as one giant string and not individual flags and arguments. As for single quotes, that's to avoid glob effect in double quotes.



              Alternatively as pipeline



              awk 'printf "-not -path %s ",$0' "$1" | xargs -L 1 find "$PWD" -type d 





              share|improve this answer






















              • The single quotes in the data would not stop the globbing patterns from expanding when you use $p unquoted.
                – Kusalananda
                Sep 14 at 18:01











              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%2f468727%2ffind-command-that-excludes-paths-listed-in-a-file%23new-answer', 'question_page');

              );

              Post as a guest






























              3 Answers
              3






              active

              oldest

              votes








              3 Answers
              3






              active

              oldest

              votes









              active

              oldest

              votes






              active

              oldest

              votes








              up vote
              3
              down vote



              accepted










              Construct an array that you later use in your call to find. The following script reads the newline-delimited path patterns from its standard input and calls find:



              #!/bin/sh

              set --

              while IFS= read -r path; do
              set -- "$@" -o -path "$path"
              done

              shift # remove initial "-o" from $@

              find . -type d ! '(' "$@" ')'


              You would run this with



              ./script.sh <paths.txt


              where paths.txt might look like



              */.git
              */.git/*
              */.vscode
              */.vscode/*
              */node_modules
              */node_modules/*
              */Image
              */Image/*
              */Rendered
              */Rendered/*
              */iNotebook
              */iNotebook/*
              */GeneratedTest
              */GeneratedTest/*
              */GeneratedOutput
              */GeneratedOutput/*
              */*_files


              Or, since your path patterns are all basically names of directories:



              #!/bin/sh

              set --

              while IFS= read -r dirname; do
              set -- "$@" -o '(' -name "$dirname" -prune ')'
              done

              shift # remove initial "-o" from $@

              find . -type d ! '(' "$@" ')'


              with the pattern file containing



              .git
              .vscode
              node_modules
              Image
              Rendered
              iNotebook
              GeneratedTest
              GeneratedOutput
              *_files


              This variant of the code would stop find from even descending into the directories matching the patterns in the file, whereas the first script (as well as your code) would test the -path patterns against everything in the excluded directories regardless of the fact that you're not interested in anything below those paths.






              share|improve this answer


























                up vote
                3
                down vote



                accepted










                Construct an array that you later use in your call to find. The following script reads the newline-delimited path patterns from its standard input and calls find:



                #!/bin/sh

                set --

                while IFS= read -r path; do
                set -- "$@" -o -path "$path"
                done

                shift # remove initial "-o" from $@

                find . -type d ! '(' "$@" ')'


                You would run this with



                ./script.sh <paths.txt


                where paths.txt might look like



                */.git
                */.git/*
                */.vscode
                */.vscode/*
                */node_modules
                */node_modules/*
                */Image
                */Image/*
                */Rendered
                */Rendered/*
                */iNotebook
                */iNotebook/*
                */GeneratedTest
                */GeneratedTest/*
                */GeneratedOutput
                */GeneratedOutput/*
                */*_files


                Or, since your path patterns are all basically names of directories:



                #!/bin/sh

                set --

                while IFS= read -r dirname; do
                set -- "$@" -o '(' -name "$dirname" -prune ')'
                done

                shift # remove initial "-o" from $@

                find . -type d ! '(' "$@" ')'


                with the pattern file containing



                .git
                .vscode
                node_modules
                Image
                Rendered
                iNotebook
                GeneratedTest
                GeneratedOutput
                *_files


                This variant of the code would stop find from even descending into the directories matching the patterns in the file, whereas the first script (as well as your code) would test the -path patterns against everything in the excluded directories regardless of the fact that you're not interested in anything below those paths.






                share|improve this answer
























                  up vote
                  3
                  down vote



                  accepted







                  up vote
                  3
                  down vote



                  accepted






                  Construct an array that you later use in your call to find. The following script reads the newline-delimited path patterns from its standard input and calls find:



                  #!/bin/sh

                  set --

                  while IFS= read -r path; do
                  set -- "$@" -o -path "$path"
                  done

                  shift # remove initial "-o" from $@

                  find . -type d ! '(' "$@" ')'


                  You would run this with



                  ./script.sh <paths.txt


                  where paths.txt might look like



                  */.git
                  */.git/*
                  */.vscode
                  */.vscode/*
                  */node_modules
                  */node_modules/*
                  */Image
                  */Image/*
                  */Rendered
                  */Rendered/*
                  */iNotebook
                  */iNotebook/*
                  */GeneratedTest
                  */GeneratedTest/*
                  */GeneratedOutput
                  */GeneratedOutput/*
                  */*_files


                  Or, since your path patterns are all basically names of directories:



                  #!/bin/sh

                  set --

                  while IFS= read -r dirname; do
                  set -- "$@" -o '(' -name "$dirname" -prune ')'
                  done

                  shift # remove initial "-o" from $@

                  find . -type d ! '(' "$@" ')'


                  with the pattern file containing



                  .git
                  .vscode
                  node_modules
                  Image
                  Rendered
                  iNotebook
                  GeneratedTest
                  GeneratedOutput
                  *_files


                  This variant of the code would stop find from even descending into the directories matching the patterns in the file, whereas the first script (as well as your code) would test the -path patterns against everything in the excluded directories regardless of the fact that you're not interested in anything below those paths.






                  share|improve this answer














                  Construct an array that you later use in your call to find. The following script reads the newline-delimited path patterns from its standard input and calls find:



                  #!/bin/sh

                  set --

                  while IFS= read -r path; do
                  set -- "$@" -o -path "$path"
                  done

                  shift # remove initial "-o" from $@

                  find . -type d ! '(' "$@" ')'


                  You would run this with



                  ./script.sh <paths.txt


                  where paths.txt might look like



                  */.git
                  */.git/*
                  */.vscode
                  */.vscode/*
                  */node_modules
                  */node_modules/*
                  */Image
                  */Image/*
                  */Rendered
                  */Rendered/*
                  */iNotebook
                  */iNotebook/*
                  */GeneratedTest
                  */GeneratedTest/*
                  */GeneratedOutput
                  */GeneratedOutput/*
                  */*_files


                  Or, since your path patterns are all basically names of directories:



                  #!/bin/sh

                  set --

                  while IFS= read -r dirname; do
                  set -- "$@" -o '(' -name "$dirname" -prune ')'
                  done

                  shift # remove initial "-o" from $@

                  find . -type d ! '(' "$@" ')'


                  with the pattern file containing



                  .git
                  .vscode
                  node_modules
                  Image
                  Rendered
                  iNotebook
                  GeneratedTest
                  GeneratedOutput
                  *_files


                  This variant of the code would stop find from even descending into the directories matching the patterns in the file, whereas the first script (as well as your code) would test the -path patterns against everything in the excluded directories regardless of the fact that you're not interested in anything below those paths.







                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited Sep 14 at 18:04

























                  answered Sep 14 at 16:36









                  Kusalananda

                  107k14209331




                  107k14209331






















                      up vote
                      2
                      down vote













                      You can use grep and find’s -exec to filter files against a list of paths, either as regular expressions or fixed strings. Adapting your example, create a file named paths containing



                      /.git$
                      /.git/
                      /.vscode$
                      /.vscode/
                      /node_modules$
                      /node_modules/
                      /Image$
                      /Image/
                      /Rendered$
                      /Rendered/
                      /iNotebook$
                      /iNotebook/
                      /GeneratedTest$
                      /GeneratedTest/
                      /GeneratedOutput$
                      /GeneratedOutput/
                      /.*_files$


                      Then run



                      find /your/search/path -type d ! -exec sh -c "echo | grep -q -f paths" ; -print


                      This looks for directories under /your/search/path, and for each one it finds, uses grep to determine whether it matches a pattern in paths; if it doesn’t, it prints it. This is intended as a base for extension; if you only care about the paths of directories which don’t match the patterns in a file, and none of the paths cover multiple lines, you can post-process the output using a single grep invocation:



                      find /your/search/path -type d | grep -v -f paths


                      If you’re really not interested in certain paths at all (i.e. your patterns always match a directory name and then everything under that directory), you could make things simpler by pruning:



                      find /your/search/path -type d ( -exec sh -c "echo | grep -q -f paths" ; -prune -o -print )


                      with the following contents in paths:



                      /.git$
                      /.vscode$
                      /node_modules$
                      /Image$
                      /Rendered$
                      /iNotebook$
                      /GeneratedTest$
                      /GeneratedOutput$
                      /.*_files$





                      share|improve this answer
























                        up vote
                        2
                        down vote













                        You can use grep and find’s -exec to filter files against a list of paths, either as regular expressions or fixed strings. Adapting your example, create a file named paths containing



                        /.git$
                        /.git/
                        /.vscode$
                        /.vscode/
                        /node_modules$
                        /node_modules/
                        /Image$
                        /Image/
                        /Rendered$
                        /Rendered/
                        /iNotebook$
                        /iNotebook/
                        /GeneratedTest$
                        /GeneratedTest/
                        /GeneratedOutput$
                        /GeneratedOutput/
                        /.*_files$


                        Then run



                        find /your/search/path -type d ! -exec sh -c "echo | grep -q -f paths" ; -print


                        This looks for directories under /your/search/path, and for each one it finds, uses grep to determine whether it matches a pattern in paths; if it doesn’t, it prints it. This is intended as a base for extension; if you only care about the paths of directories which don’t match the patterns in a file, and none of the paths cover multiple lines, you can post-process the output using a single grep invocation:



                        find /your/search/path -type d | grep -v -f paths


                        If you’re really not interested in certain paths at all (i.e. your patterns always match a directory name and then everything under that directory), you could make things simpler by pruning:



                        find /your/search/path -type d ( -exec sh -c "echo | grep -q -f paths" ; -prune -o -print )


                        with the following contents in paths:



                        /.git$
                        /.vscode$
                        /node_modules$
                        /Image$
                        /Rendered$
                        /iNotebook$
                        /GeneratedTest$
                        /GeneratedOutput$
                        /.*_files$





                        share|improve this answer






















                          up vote
                          2
                          down vote










                          up vote
                          2
                          down vote









                          You can use grep and find’s -exec to filter files against a list of paths, either as regular expressions or fixed strings. Adapting your example, create a file named paths containing



                          /.git$
                          /.git/
                          /.vscode$
                          /.vscode/
                          /node_modules$
                          /node_modules/
                          /Image$
                          /Image/
                          /Rendered$
                          /Rendered/
                          /iNotebook$
                          /iNotebook/
                          /GeneratedTest$
                          /GeneratedTest/
                          /GeneratedOutput$
                          /GeneratedOutput/
                          /.*_files$


                          Then run



                          find /your/search/path -type d ! -exec sh -c "echo | grep -q -f paths" ; -print


                          This looks for directories under /your/search/path, and for each one it finds, uses grep to determine whether it matches a pattern in paths; if it doesn’t, it prints it. This is intended as a base for extension; if you only care about the paths of directories which don’t match the patterns in a file, and none of the paths cover multiple lines, you can post-process the output using a single grep invocation:



                          find /your/search/path -type d | grep -v -f paths


                          If you’re really not interested in certain paths at all (i.e. your patterns always match a directory name and then everything under that directory), you could make things simpler by pruning:



                          find /your/search/path -type d ( -exec sh -c "echo | grep -q -f paths" ; -prune -o -print )


                          with the following contents in paths:



                          /.git$
                          /.vscode$
                          /node_modules$
                          /Image$
                          /Rendered$
                          /iNotebook$
                          /GeneratedTest$
                          /GeneratedOutput$
                          /.*_files$





                          share|improve this answer












                          You can use grep and find’s -exec to filter files against a list of paths, either as regular expressions or fixed strings. Adapting your example, create a file named paths containing



                          /.git$
                          /.git/
                          /.vscode$
                          /.vscode/
                          /node_modules$
                          /node_modules/
                          /Image$
                          /Image/
                          /Rendered$
                          /Rendered/
                          /iNotebook$
                          /iNotebook/
                          /GeneratedTest$
                          /GeneratedTest/
                          /GeneratedOutput$
                          /GeneratedOutput/
                          /.*_files$


                          Then run



                          find /your/search/path -type d ! -exec sh -c "echo | grep -q -f paths" ; -print


                          This looks for directories under /your/search/path, and for each one it finds, uses grep to determine whether it matches a pattern in paths; if it doesn’t, it prints it. This is intended as a base for extension; if you only care about the paths of directories which don’t match the patterns in a file, and none of the paths cover multiple lines, you can post-process the output using a single grep invocation:



                          find /your/search/path -type d | grep -v -f paths


                          If you’re really not interested in certain paths at all (i.e. your patterns always match a directory name and then everything under that directory), you could make things simpler by pruning:



                          find /your/search/path -type d ( -exec sh -c "echo | grep -q -f paths" ; -prune -o -print )


                          with the following contents in paths:



                          /.git$
                          /.vscode$
                          /node_modules$
                          /Image$
                          /Rendered$
                          /iNotebook$
                          /GeneratedTest$
                          /GeneratedOutput$
                          /.*_files$






                          share|improve this answer












                          share|improve this answer



                          share|improve this answer










                          answered Sep 14 at 12:50









                          Stephen Kitt

                          148k22324393




                          148k22324393




















                              up vote
                              1
                              down vote













                              What can be done is to built up the command using awk and pass it to find as variable in a "wrapper" script or shell function



                              p=$( awk 'printf "-not -path %s ",$0' "$1" )
                              find "$PWD" $p -type d


                              And call it as ./find_wrapper.sh paths.txt, where path.txt is the list of quoted paths.



                              '*/.git'
                              '*/.git/*'
                              '*/.vscode'
                              '*/.vscode/*'
                              '*/node_modules'
                              '*/node_modules/*'
                              '*/Image'
                              ...


                              Why it's done this way ? The reason awk builts a one whole line is because there's no reason to do that in script - the line continuations are for making the command look more organized, but functionally it doesn't give any advantage. $p is unquoted, since we actually want word splitting here. Otherwise find sees it as one giant string and not individual flags and arguments. As for single quotes, that's to avoid glob effect in double quotes.



                              Alternatively as pipeline



                              awk 'printf "-not -path %s ",$0' "$1" | xargs -L 1 find "$PWD" -type d 





                              share|improve this answer






















                              • The single quotes in the data would not stop the globbing patterns from expanding when you use $p unquoted.
                                – Kusalananda
                                Sep 14 at 18:01















                              up vote
                              1
                              down vote













                              What can be done is to built up the command using awk and pass it to find as variable in a "wrapper" script or shell function



                              p=$( awk 'printf "-not -path %s ",$0' "$1" )
                              find "$PWD" $p -type d


                              And call it as ./find_wrapper.sh paths.txt, where path.txt is the list of quoted paths.



                              '*/.git'
                              '*/.git/*'
                              '*/.vscode'
                              '*/.vscode/*'
                              '*/node_modules'
                              '*/node_modules/*'
                              '*/Image'
                              ...


                              Why it's done this way ? The reason awk builts a one whole line is because there's no reason to do that in script - the line continuations are for making the command look more organized, but functionally it doesn't give any advantage. $p is unquoted, since we actually want word splitting here. Otherwise find sees it as one giant string and not individual flags and arguments. As for single quotes, that's to avoid glob effect in double quotes.



                              Alternatively as pipeline



                              awk 'printf "-not -path %s ",$0' "$1" | xargs -L 1 find "$PWD" -type d 





                              share|improve this answer






















                              • The single quotes in the data would not stop the globbing patterns from expanding when you use $p unquoted.
                                – Kusalananda
                                Sep 14 at 18:01













                              up vote
                              1
                              down vote










                              up vote
                              1
                              down vote









                              What can be done is to built up the command using awk and pass it to find as variable in a "wrapper" script or shell function



                              p=$( awk 'printf "-not -path %s ",$0' "$1" )
                              find "$PWD" $p -type d


                              And call it as ./find_wrapper.sh paths.txt, where path.txt is the list of quoted paths.



                              '*/.git'
                              '*/.git/*'
                              '*/.vscode'
                              '*/.vscode/*'
                              '*/node_modules'
                              '*/node_modules/*'
                              '*/Image'
                              ...


                              Why it's done this way ? The reason awk builts a one whole line is because there's no reason to do that in script - the line continuations are for making the command look more organized, but functionally it doesn't give any advantage. $p is unquoted, since we actually want word splitting here. Otherwise find sees it as one giant string and not individual flags and arguments. As for single quotes, that's to avoid glob effect in double quotes.



                              Alternatively as pipeline



                              awk 'printf "-not -path %s ",$0' "$1" | xargs -L 1 find "$PWD" -type d 





                              share|improve this answer














                              What can be done is to built up the command using awk and pass it to find as variable in a "wrapper" script or shell function



                              p=$( awk 'printf "-not -path %s ",$0' "$1" )
                              find "$PWD" $p -type d


                              And call it as ./find_wrapper.sh paths.txt, where path.txt is the list of quoted paths.



                              '*/.git'
                              '*/.git/*'
                              '*/.vscode'
                              '*/.vscode/*'
                              '*/node_modules'
                              '*/node_modules/*'
                              '*/Image'
                              ...


                              Why it's done this way ? The reason awk builts a one whole line is because there's no reason to do that in script - the line continuations are for making the command look more organized, but functionally it doesn't give any advantage. $p is unquoted, since we actually want word splitting here. Otherwise find sees it as one giant string and not individual flags and arguments. As for single quotes, that's to avoid glob effect in double quotes.



                              Alternatively as pipeline



                              awk 'printf "-not -path %s ",$0' "$1" | xargs -L 1 find "$PWD" -type d 






                              share|improve this answer














                              share|improve this answer



                              share|improve this answer








                              edited Sep 14 at 16:50

























                              answered Sep 14 at 16:01









                              Sergiy Kolodyazhnyy

                              7,95011848




                              7,95011848











                              • The single quotes in the data would not stop the globbing patterns from expanding when you use $p unquoted.
                                – Kusalananda
                                Sep 14 at 18:01

















                              • The single quotes in the data would not stop the globbing patterns from expanding when you use $p unquoted.
                                – Kusalananda
                                Sep 14 at 18:01
















                              The single quotes in the data would not stop the globbing patterns from expanding when you use $p unquoted.
                              – Kusalananda
                              Sep 14 at 18:01





                              The single quotes in the data would not stop the globbing patterns from expanding when you use $p unquoted.
                              – Kusalananda
                              Sep 14 at 18:01


















                               

                              draft saved


                              draft discarded















































                               


                              draft saved


                              draft discarded














                              StackExchange.ready(
                              function ()
                              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f468727%2ffind-command-that-excludes-paths-listed-in-a-file%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?