using awk with find -exec












3















I have a directory structure with 14 directories containing a bunch of files containing data in a three-column format (separated with tabs). I intended to use find and awk to extract the second column from each of those files and output it with the same filename but under a different root folder. Here the sketch of my directory.



data/all -> AA, AB, AC, AD ... (A* being folders containing the files with data stored in a 3-column format, e.g. AA100.txt, AA101.txt ...)



i want to have the modified (one-column) files with the same name, but all under a new root directory data/pos (as opposed to data/all/) -> AA, AB, AC, AD ... (again, each containing A*100.txt, A*101...)



My try was to use find -exec and to give it the awk command, but I'm having issues with outputting the file to the right place.



when being in data/all/





find * -type f -exec awk '{print$2}' '{}' > ../pos/'{}' ;





However {} as wildcard for the input file doesn't seem to work when outputting the file?



What am I doing wrong? (I'm on a ubuntu server btw)










share|improve this question



























    3















    I have a directory structure with 14 directories containing a bunch of files containing data in a three-column format (separated with tabs). I intended to use find and awk to extract the second column from each of those files and output it with the same filename but under a different root folder. Here the sketch of my directory.



    data/all -> AA, AB, AC, AD ... (A* being folders containing the files with data stored in a 3-column format, e.g. AA100.txt, AA101.txt ...)



    i want to have the modified (one-column) files with the same name, but all under a new root directory data/pos (as opposed to data/all/) -> AA, AB, AC, AD ... (again, each containing A*100.txt, A*101...)



    My try was to use find -exec and to give it the awk command, but I'm having issues with outputting the file to the right place.



    when being in data/all/





    find * -type f -exec awk '{print$2}' '{}' > ../pos/'{}' ;





    However {} as wildcard for the input file doesn't seem to work when outputting the file?



    What am I doing wrong? (I'm on a ubuntu server btw)










    share|improve this question

























      3












      3








      3








      I have a directory structure with 14 directories containing a bunch of files containing data in a three-column format (separated with tabs). I intended to use find and awk to extract the second column from each of those files and output it with the same filename but under a different root folder. Here the sketch of my directory.



      data/all -> AA, AB, AC, AD ... (A* being folders containing the files with data stored in a 3-column format, e.g. AA100.txt, AA101.txt ...)



      i want to have the modified (one-column) files with the same name, but all under a new root directory data/pos (as opposed to data/all/) -> AA, AB, AC, AD ... (again, each containing A*100.txt, A*101...)



      My try was to use find -exec and to give it the awk command, but I'm having issues with outputting the file to the right place.



      when being in data/all/





      find * -type f -exec awk '{print$2}' '{}' > ../pos/'{}' ;





      However {} as wildcard for the input file doesn't seem to work when outputting the file?



      What am I doing wrong? (I'm on a ubuntu server btw)










      share|improve this question














      I have a directory structure with 14 directories containing a bunch of files containing data in a three-column format (separated with tabs). I intended to use find and awk to extract the second column from each of those files and output it with the same filename but under a different root folder. Here the sketch of my directory.



      data/all -> AA, AB, AC, AD ... (A* being folders containing the files with data stored in a 3-column format, e.g. AA100.txt, AA101.txt ...)



      i want to have the modified (one-column) files with the same name, but all under a new root directory data/pos (as opposed to data/all/) -> AA, AB, AC, AD ... (again, each containing A*100.txt, A*101...)



      My try was to use find -exec and to give it the awk command, but I'm having issues with outputting the file to the right place.



      when being in data/all/





      find * -type f -exec awk '{print$2}' '{}' > ../pos/'{}' ;





      However {} as wildcard for the input file doesn't seem to work when outputting the file?



      What am I doing wrong? (I'm on a ubuntu server btw)







      unix find awk






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Dec 18 '13 at 13:44









      conipoconipo

      25114




      25114






















          3 Answers
          3






          active

          oldest

          votes


















          3














          You could try without find, if all you want is all the files. While in data/all/, run this:



          for file in ./*; do awk '{print$2}' "$file" > "../pos/$(basename $file)"; done


          If you want to cover the files in the whole hierarchy under /data/all, you can enable the globstar option if you are using bash (I believe this would "just work" on zsh) and then use ** to match all files:



          shopt -s globstar
          for file in ./**; do awk '{print$2}' "$file" > "../pos/$(basename $file)"; done





          share|improve this answer


























          • Using for */* did the trick for me though, the globstar option wasn't available for me.

            – conipo
            Dec 19 '13 at 19:44



















          5















          What am I doing wrong?




          You are using the redirection > ../pos/'{}' as if it was handled by find or awk but redirections are handled by the shell. In your case it means that you can redirect only output of the whole find (not output of awk).



          Note that you do not usually need to use wildcard like * for the starting path of find. Is the common way find . what you wanted to do or is there any reason for find *?



          Solutions



          Here we will keep the flexibility of find in contrast to the solution by Jacobo de Vera.
          Run awk in a shell loop:



          find . -type f -print0 |
          while read -r -d $'' x; do
          awk '{print $2}' "$x" > "../pos/$(basename "$x")"
          done


          The original way with -exec will be less efficient because for every file a shell will be launched in addition to awk and the multi-level escaping is pretty complicated here:



          find . -type f -exec sh -c 'awk "{print $2}" "{}" > "../pos/{}"' ;


          There could also be an alternative solution of doing the redirection inside awk.






          share|improve this answer
























          • I used the wildcard * in order to avoid the avoid the ./ in the path (as it gave me an error message that it could not find the specified path, which was something like pos/./AA/AA101.txt -> I had assumed the error to be there, that's why I used the * instead)

            – conipo
            Dec 19 '13 at 19:42



















          -1














          find /path -exec ls -l {} ; | awk '{print$1}'






          share|improve this answer























            Your Answer








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

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

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


            }
            });














            draft saved

            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fsuperuser.com%2fquestions%2f690116%2fusing-awk-with-find-exec%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









            3














            You could try without find, if all you want is all the files. While in data/all/, run this:



            for file in ./*; do awk '{print$2}' "$file" > "../pos/$(basename $file)"; done


            If you want to cover the files in the whole hierarchy under /data/all, you can enable the globstar option if you are using bash (I believe this would "just work" on zsh) and then use ** to match all files:



            shopt -s globstar
            for file in ./**; do awk '{print$2}' "$file" > "../pos/$(basename $file)"; done





            share|improve this answer


























            • Using for */* did the trick for me though, the globstar option wasn't available for me.

              – conipo
              Dec 19 '13 at 19:44
















            3














            You could try without find, if all you want is all the files. While in data/all/, run this:



            for file in ./*; do awk '{print$2}' "$file" > "../pos/$(basename $file)"; done


            If you want to cover the files in the whole hierarchy under /data/all, you can enable the globstar option if you are using bash (I believe this would "just work" on zsh) and then use ** to match all files:



            shopt -s globstar
            for file in ./**; do awk '{print$2}' "$file" > "../pos/$(basename $file)"; done





            share|improve this answer


























            • Using for */* did the trick for me though, the globstar option wasn't available for me.

              – conipo
              Dec 19 '13 at 19:44














            3












            3








            3







            You could try without find, if all you want is all the files. While in data/all/, run this:



            for file in ./*; do awk '{print$2}' "$file" > "../pos/$(basename $file)"; done


            If you want to cover the files in the whole hierarchy under /data/all, you can enable the globstar option if you are using bash (I believe this would "just work" on zsh) and then use ** to match all files:



            shopt -s globstar
            for file in ./**; do awk '{print$2}' "$file" > "../pos/$(basename $file)"; done





            share|improve this answer















            You could try without find, if all you want is all the files. While in data/all/, run this:



            for file in ./*; do awk '{print$2}' "$file" > "../pos/$(basename $file)"; done


            If you want to cover the files in the whole hierarchy under /data/all, you can enable the globstar option if you are using bash (I believe this would "just work" on zsh) and then use ** to match all files:



            shopt -s globstar
            for file in ./**; do awk '{print$2}' "$file" > "../pos/$(basename $file)"; done






            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Dec 18 '13 at 13:58

























            answered Dec 18 '13 at 13:50









            Jacobo de VeraJacobo de Vera

            24217




            24217













            • Using for */* did the trick for me though, the globstar option wasn't available for me.

              – conipo
              Dec 19 '13 at 19:44



















            • Using for */* did the trick for me though, the globstar option wasn't available for me.

              – conipo
              Dec 19 '13 at 19:44

















            Using for */* did the trick for me though, the globstar option wasn't available for me.

            – conipo
            Dec 19 '13 at 19:44





            Using for */* did the trick for me though, the globstar option wasn't available for me.

            – conipo
            Dec 19 '13 at 19:44













            5















            What am I doing wrong?




            You are using the redirection > ../pos/'{}' as if it was handled by find or awk but redirections are handled by the shell. In your case it means that you can redirect only output of the whole find (not output of awk).



            Note that you do not usually need to use wildcard like * for the starting path of find. Is the common way find . what you wanted to do or is there any reason for find *?



            Solutions



            Here we will keep the flexibility of find in contrast to the solution by Jacobo de Vera.
            Run awk in a shell loop:



            find . -type f -print0 |
            while read -r -d $'' x; do
            awk '{print $2}' "$x" > "../pos/$(basename "$x")"
            done


            The original way with -exec will be less efficient because for every file a shell will be launched in addition to awk and the multi-level escaping is pretty complicated here:



            find . -type f -exec sh -c 'awk "{print $2}" "{}" > "../pos/{}"' ;


            There could also be an alternative solution of doing the redirection inside awk.






            share|improve this answer
























            • I used the wildcard * in order to avoid the avoid the ./ in the path (as it gave me an error message that it could not find the specified path, which was something like pos/./AA/AA101.txt -> I had assumed the error to be there, that's why I used the * instead)

              – conipo
              Dec 19 '13 at 19:42
















            5















            What am I doing wrong?




            You are using the redirection > ../pos/'{}' as if it was handled by find or awk but redirections are handled by the shell. In your case it means that you can redirect only output of the whole find (not output of awk).



            Note that you do not usually need to use wildcard like * for the starting path of find. Is the common way find . what you wanted to do or is there any reason for find *?



            Solutions



            Here we will keep the flexibility of find in contrast to the solution by Jacobo de Vera.
            Run awk in a shell loop:



            find . -type f -print0 |
            while read -r -d $'' x; do
            awk '{print $2}' "$x" > "../pos/$(basename "$x")"
            done


            The original way with -exec will be less efficient because for every file a shell will be launched in addition to awk and the multi-level escaping is pretty complicated here:



            find . -type f -exec sh -c 'awk "{print $2}" "{}" > "../pos/{}"' ;


            There could also be an alternative solution of doing the redirection inside awk.






            share|improve this answer
























            • I used the wildcard * in order to avoid the avoid the ./ in the path (as it gave me an error message that it could not find the specified path, which was something like pos/./AA/AA101.txt -> I had assumed the error to be there, that's why I used the * instead)

              – conipo
              Dec 19 '13 at 19:42














            5












            5








            5








            What am I doing wrong?




            You are using the redirection > ../pos/'{}' as if it was handled by find or awk but redirections are handled by the shell. In your case it means that you can redirect only output of the whole find (not output of awk).



            Note that you do not usually need to use wildcard like * for the starting path of find. Is the common way find . what you wanted to do or is there any reason for find *?



            Solutions



            Here we will keep the flexibility of find in contrast to the solution by Jacobo de Vera.
            Run awk in a shell loop:



            find . -type f -print0 |
            while read -r -d $'' x; do
            awk '{print $2}' "$x" > "../pos/$(basename "$x")"
            done


            The original way with -exec will be less efficient because for every file a shell will be launched in addition to awk and the multi-level escaping is pretty complicated here:



            find . -type f -exec sh -c 'awk "{print $2}" "{}" > "../pos/{}"' ;


            There could also be an alternative solution of doing the redirection inside awk.






            share|improve this answer














            What am I doing wrong?




            You are using the redirection > ../pos/'{}' as if it was handled by find or awk but redirections are handled by the shell. In your case it means that you can redirect only output of the whole find (not output of awk).



            Note that you do not usually need to use wildcard like * for the starting path of find. Is the common way find . what you wanted to do or is there any reason for find *?



            Solutions



            Here we will keep the flexibility of find in contrast to the solution by Jacobo de Vera.
            Run awk in a shell loop:



            find . -type f -print0 |
            while read -r -d $'' x; do
            awk '{print $2}' "$x" > "../pos/$(basename "$x")"
            done


            The original way with -exec will be less efficient because for every file a shell will be launched in addition to awk and the multi-level escaping is pretty complicated here:



            find . -type f -exec sh -c 'awk "{print $2}" "{}" > "../pos/{}"' ;


            There could also be an alternative solution of doing the redirection inside awk.







            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Dec 18 '13 at 15:02









            paboukpabouk

            4,93853146




            4,93853146













            • I used the wildcard * in order to avoid the avoid the ./ in the path (as it gave me an error message that it could not find the specified path, which was something like pos/./AA/AA101.txt -> I had assumed the error to be there, that's why I used the * instead)

              – conipo
              Dec 19 '13 at 19:42



















            • I used the wildcard * in order to avoid the avoid the ./ in the path (as it gave me an error message that it could not find the specified path, which was something like pos/./AA/AA101.txt -> I had assumed the error to be there, that's why I used the * instead)

              – conipo
              Dec 19 '13 at 19:42

















            I used the wildcard * in order to avoid the avoid the ./ in the path (as it gave me an error message that it could not find the specified path, which was something like pos/./AA/AA101.txt -> I had assumed the error to be there, that's why I used the * instead)

            – conipo
            Dec 19 '13 at 19:42





            I used the wildcard * in order to avoid the avoid the ./ in the path (as it gave me an error message that it could not find the specified path, which was something like pos/./AA/AA101.txt -> I had assumed the error to be there, that's why I used the * instead)

            – conipo
            Dec 19 '13 at 19:42











            -1














            find /path -exec ls -l {} ; | awk '{print$1}'






            share|improve this answer




























              -1














              find /path -exec ls -l {} ; | awk '{print$1}'






              share|improve this answer


























                -1












                -1








                -1







                find /path -exec ls -l {} ; | awk '{print$1}'






                share|improve this answer













                find /path -exec ls -l {} ; | awk '{print$1}'







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Jan 7 at 9:41









                mantasmantas

                1




                1






























                    draft saved

                    draft discarded




















































                    Thanks for contributing an answer to Super User!


                    • 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%2fsuperuser.com%2fquestions%2f690116%2fusing-awk-with-find-exec%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

                    "Incorrect syntax near the keyword 'ON'. (on update cascade, on delete cascade,)

                    Alcedinidae

                    Origin of the phrase “under your belt”?