Bash: pipe 'find' output into 'readarray'

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











up vote
5
down vote

favorite
2












I'm trying to search for files using find, and put those files into a Bash array so that I can do other operations on them (e.g. ls or grep them). But I can't figure out why readarray isn't reading the find output as it's piped into it.



Say I have two files in the current directory, file1.txt and file2.txt. So the find output is as follows:



$ find . -name "file*"
./file1.txt
./file2.txt


So I want to pipe that into an array whose two elements are the strings "./file1.txt" and "./file2.txt" (without quotes, obviously).



I've tried this, among a few other things:



$ declare -a FILES
$ find . -name "file*" | readarray FILES
$ echo "$FILES[@]"; echo "$#FILES[@]"

0


As you can see from the echo output, my array is empty.



So what exactly am I doing wrong here? Why is readarray not reading find's output as its standard input and putting those strings into the array?










share|improve this question

























    up vote
    5
    down vote

    favorite
    2












    I'm trying to search for files using find, and put those files into a Bash array so that I can do other operations on them (e.g. ls or grep them). But I can't figure out why readarray isn't reading the find output as it's piped into it.



    Say I have two files in the current directory, file1.txt and file2.txt. So the find output is as follows:



    $ find . -name "file*"
    ./file1.txt
    ./file2.txt


    So I want to pipe that into an array whose two elements are the strings "./file1.txt" and "./file2.txt" (without quotes, obviously).



    I've tried this, among a few other things:



    $ declare -a FILES
    $ find . -name "file*" | readarray FILES
    $ echo "$FILES[@]"; echo "$#FILES[@]"

    0


    As you can see from the echo output, my array is empty.



    So what exactly am I doing wrong here? Why is readarray not reading find's output as its standard input and putting those strings into the array?










    share|improve this question























      up vote
      5
      down vote

      favorite
      2









      up vote
      5
      down vote

      favorite
      2






      2





      I'm trying to search for files using find, and put those files into a Bash array so that I can do other operations on them (e.g. ls or grep them). But I can't figure out why readarray isn't reading the find output as it's piped into it.



      Say I have two files in the current directory, file1.txt and file2.txt. So the find output is as follows:



      $ find . -name "file*"
      ./file1.txt
      ./file2.txt


      So I want to pipe that into an array whose two elements are the strings "./file1.txt" and "./file2.txt" (without quotes, obviously).



      I've tried this, among a few other things:



      $ declare -a FILES
      $ find . -name "file*" | readarray FILES
      $ echo "$FILES[@]"; echo "$#FILES[@]"

      0


      As you can see from the echo output, my array is empty.



      So what exactly am I doing wrong here? Why is readarray not reading find's output as its standard input and putting those strings into the array?










      share|improve this question













      I'm trying to search for files using find, and put those files into a Bash array so that I can do other operations on them (e.g. ls or grep them). But I can't figure out why readarray isn't reading the find output as it's piped into it.



      Say I have two files in the current directory, file1.txt and file2.txt. So the find output is as follows:



      $ find . -name "file*"
      ./file1.txt
      ./file2.txt


      So I want to pipe that into an array whose two elements are the strings "./file1.txt" and "./file2.txt" (without quotes, obviously).



      I've tried this, among a few other things:



      $ declare -a FILES
      $ find . -name "file*" | readarray FILES
      $ echo "$FILES[@]"; echo "$#FILES[@]"

      0


      As you can see from the echo output, my array is empty.



      So what exactly am I doing wrong here? Why is readarray not reading find's output as its standard input and putting those strings into the array?







      bash find






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Feb 17 '16 at 16:16









      villapx

      21028




      21028




















          3 Answers
          3






          active

          oldest

          votes

















          up vote
          12
          down vote



          accepted










          When using a pipeline, bash runs the commands in subshells. Therefore, the array is populated, but in a subshell, so the parent shell has no access to it.



          Use process substitution:



          readarray FILES < <(find)


          Note that it doesn't work for files with newlines in their names. If that could be the case, you need a more elaborate syntax:



          readarray -d '' < <(find -print0)





          share|improve this answer






















          • Awesome. Thanks for explaining that
            – villapx
            Feb 17 '16 at 16:34






          • 2




            In order to support newlines, this is sufficient: readarray -d '' < <(find your_args -print0)
            – VasyaNovikov
            Jan 18 at 13:40

















          up vote
          5
          down vote













          The correct solution is:



          unset a; declare -a a
          while IFS= read -r -u3 -d $'' file; do
          a+=( "$file" ) # or however you want to process each file
          done 3< <(find /tmp -type f -print0)


          That's similar to what Greg's BashFAQ 020 explains in detail and this answer covers.



          Has no problem with odd named files (that contain no NUL in the name), with spaces or new lines. And the result is set in an array, which makes it useful for further processing.






          share|improve this answer






















          • Great, this is a better solution to the problem I was trying to solve in the first place. +1 as soon as my rep reaches 15 :)
            – villapx
            Feb 17 '16 at 19:12

















          up vote
          2
          down vote













          readarray can also read from stdin



          readarray FILES <<< "$(find . -name "file*")"; echo "$#FILES[@]"





          share|improve this answer






















            Your Answer








            StackExchange.ready(function()
            var channelOptions =
            tags: "".split(" "),
            id: "106"
            ;
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function()
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled)
            StackExchange.using("snippets", function()
            createEditor();
            );

            else
            createEditor();

            );

            function createEditor()
            StackExchange.prepareEditor(
            heartbeatType: 'answer',
            convertImagesToLinks: false,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: null,
            bindNavPrevention: true,
            postfix: "",
            imageUploader:
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            ,
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            );



            );













            draft saved

            draft discarded


















            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f263883%2fbash-pipe-find-output-into-readarray%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown

























            3 Answers
            3






            active

            oldest

            votes








            3 Answers
            3






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes








            up vote
            12
            down vote



            accepted










            When using a pipeline, bash runs the commands in subshells. Therefore, the array is populated, but in a subshell, so the parent shell has no access to it.



            Use process substitution:



            readarray FILES < <(find)


            Note that it doesn't work for files with newlines in their names. If that could be the case, you need a more elaborate syntax:



            readarray -d '' < <(find -print0)





            share|improve this answer






















            • Awesome. Thanks for explaining that
              – villapx
              Feb 17 '16 at 16:34






            • 2




              In order to support newlines, this is sufficient: readarray -d '' < <(find your_args -print0)
              – VasyaNovikov
              Jan 18 at 13:40














            up vote
            12
            down vote



            accepted










            When using a pipeline, bash runs the commands in subshells. Therefore, the array is populated, but in a subshell, so the parent shell has no access to it.



            Use process substitution:



            readarray FILES < <(find)


            Note that it doesn't work for files with newlines in their names. If that could be the case, you need a more elaborate syntax:



            readarray -d '' < <(find -print0)





            share|improve this answer






















            • Awesome. Thanks for explaining that
              – villapx
              Feb 17 '16 at 16:34






            • 2




              In order to support newlines, this is sufficient: readarray -d '' < <(find your_args -print0)
              – VasyaNovikov
              Jan 18 at 13:40












            up vote
            12
            down vote



            accepted







            up vote
            12
            down vote



            accepted






            When using a pipeline, bash runs the commands in subshells. Therefore, the array is populated, but in a subshell, so the parent shell has no access to it.



            Use process substitution:



            readarray FILES < <(find)


            Note that it doesn't work for files with newlines in their names. If that could be the case, you need a more elaborate syntax:



            readarray -d '' < <(find -print0)





            share|improve this answer














            When using a pipeline, bash runs the commands in subshells. Therefore, the array is populated, but in a subshell, so the parent shell has no access to it.



            Use process substitution:



            readarray FILES < <(find)


            Note that it doesn't work for files with newlines in their names. If that could be the case, you need a more elaborate syntax:



            readarray -d '' < <(find -print0)






            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Nov 26 at 8:28

























            answered Feb 17 '16 at 16:25









            choroba

            26k44570




            26k44570











            • Awesome. Thanks for explaining that
              – villapx
              Feb 17 '16 at 16:34






            • 2




              In order to support newlines, this is sufficient: readarray -d '' < <(find your_args -print0)
              – VasyaNovikov
              Jan 18 at 13:40
















            • Awesome. Thanks for explaining that
              – villapx
              Feb 17 '16 at 16:34






            • 2




              In order to support newlines, this is sufficient: readarray -d '' < <(find your_args -print0)
              – VasyaNovikov
              Jan 18 at 13:40















            Awesome. Thanks for explaining that
            – villapx
            Feb 17 '16 at 16:34




            Awesome. Thanks for explaining that
            – villapx
            Feb 17 '16 at 16:34




            2




            2




            In order to support newlines, this is sufficient: readarray -d '' < <(find your_args -print0)
            – VasyaNovikov
            Jan 18 at 13:40




            In order to support newlines, this is sufficient: readarray -d '' < <(find your_args -print0)
            – VasyaNovikov
            Jan 18 at 13:40












            up vote
            5
            down vote













            The correct solution is:



            unset a; declare -a a
            while IFS= read -r -u3 -d $'' file; do
            a+=( "$file" ) # or however you want to process each file
            done 3< <(find /tmp -type f -print0)


            That's similar to what Greg's BashFAQ 020 explains in detail and this answer covers.



            Has no problem with odd named files (that contain no NUL in the name), with spaces or new lines. And the result is set in an array, which makes it useful for further processing.






            share|improve this answer






















            • Great, this is a better solution to the problem I was trying to solve in the first place. +1 as soon as my rep reaches 15 :)
              – villapx
              Feb 17 '16 at 19:12














            up vote
            5
            down vote













            The correct solution is:



            unset a; declare -a a
            while IFS= read -r -u3 -d $'' file; do
            a+=( "$file" ) # or however you want to process each file
            done 3< <(find /tmp -type f -print0)


            That's similar to what Greg's BashFAQ 020 explains in detail and this answer covers.



            Has no problem with odd named files (that contain no NUL in the name), with spaces or new lines. And the result is set in an array, which makes it useful for further processing.






            share|improve this answer






















            • Great, this is a better solution to the problem I was trying to solve in the first place. +1 as soon as my rep reaches 15 :)
              – villapx
              Feb 17 '16 at 19:12












            up vote
            5
            down vote










            up vote
            5
            down vote









            The correct solution is:



            unset a; declare -a a
            while IFS= read -r -u3 -d $'' file; do
            a+=( "$file" ) # or however you want to process each file
            done 3< <(find /tmp -type f -print0)


            That's similar to what Greg's BashFAQ 020 explains in detail and this answer covers.



            Has no problem with odd named files (that contain no NUL in the name), with spaces or new lines. And the result is set in an array, which makes it useful for further processing.






            share|improve this answer














            The correct solution is:



            unset a; declare -a a
            while IFS= read -r -u3 -d $'' file; do
            a+=( "$file" ) # or however you want to process each file
            done 3< <(find /tmp -type f -print0)


            That's similar to what Greg's BashFAQ 020 explains in detail and this answer covers.



            Has no problem with odd named files (that contain no NUL in the name), with spaces or new lines. And the result is set in an array, which makes it useful for further processing.







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited May 23 '17 at 12:39









            Community

            1




            1










            answered Feb 17 '16 at 18:40







            user79743


















            • Great, this is a better solution to the problem I was trying to solve in the first place. +1 as soon as my rep reaches 15 :)
              – villapx
              Feb 17 '16 at 19:12
















            • Great, this is a better solution to the problem I was trying to solve in the first place. +1 as soon as my rep reaches 15 :)
              – villapx
              Feb 17 '16 at 19:12















            Great, this is a better solution to the problem I was trying to solve in the first place. +1 as soon as my rep reaches 15 :)
            – villapx
            Feb 17 '16 at 19:12




            Great, this is a better solution to the problem I was trying to solve in the first place. +1 as soon as my rep reaches 15 :)
            – villapx
            Feb 17 '16 at 19:12










            up vote
            2
            down vote













            readarray can also read from stdin



            readarray FILES <<< "$(find . -name "file*")"; echo "$#FILES[@]"





            share|improve this answer


























              up vote
              2
              down vote













              readarray can also read from stdin



              readarray FILES <<< "$(find . -name "file*")"; echo "$#FILES[@]"





              share|improve this answer
























                up vote
                2
                down vote










                up vote
                2
                down vote









                readarray can also read from stdin



                readarray FILES <<< "$(find . -name "file*")"; echo "$#FILES[@]"





                share|improve this answer














                readarray can also read from stdin



                readarray FILES <<< "$(find . -name "file*")"; echo "$#FILES[@]"






                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited Nov 11 '16 at 5:16

























                answered Nov 11 '16 at 5:08









                smac89

                19719




                19719



























                    draft saved

                    draft discarded
















































                    Thanks for contributing an answer to Unix & Linux Stack Exchange!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid


                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.

                    To learn more, see our tips on writing great answers.





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


                    Please pay close attention to the following guidance:


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid


                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.

                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function ()
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f263883%2fbash-pipe-find-output-into-readarray%23new-answer', 'question_page');

                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown






                    Popular posts from this blog

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

                    Displaying single band from multi-band raster using QGIS

                    How many registers does an x86_64 CPU actually have?