Script to rename a large number of files using the text in each file to rename












1















I am trying to devise a solution to rename a large collection of files so that the text in line 3 of each file is the new filename. These files all have the same structure. My scripting ability is poor so I am hoping this problem has been approached before by others so I don't need to invent a new wheel? I've been consulting some sed and awk tutorials but not finding a solution there.



These are HTML files and specifically line 3 of each file looks like this.



<TITLE>DATA POPULATION 'CODE on group 1234 by THING'</TITLE>


I want to grab everything between the single quotes and use that text to rename the file with that text as the filename.



Can anyone point me down the right path to approach this task? The notion of renaming these one at a time would just be murder.



Thanks for reading and pondering this problem.










share|improve this question









New contributor




Daniel Cross is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.

























    1















    I am trying to devise a solution to rename a large collection of files so that the text in line 3 of each file is the new filename. These files all have the same structure. My scripting ability is poor so I am hoping this problem has been approached before by others so I don't need to invent a new wheel? I've been consulting some sed and awk tutorials but not finding a solution there.



    These are HTML files and specifically line 3 of each file looks like this.



    <TITLE>DATA POPULATION 'CODE on group 1234 by THING'</TITLE>


    I want to grab everything between the single quotes and use that text to rename the file with that text as the filename.



    Can anyone point me down the right path to approach this task? The notion of renaming these one at a time would just be murder.



    Thanks for reading and pondering this problem.










    share|improve this question









    New contributor




    Daniel Cross is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
    Check out our Code of Conduct.























      1












      1








      1








      I am trying to devise a solution to rename a large collection of files so that the text in line 3 of each file is the new filename. These files all have the same structure. My scripting ability is poor so I am hoping this problem has been approached before by others so I don't need to invent a new wheel? I've been consulting some sed and awk tutorials but not finding a solution there.



      These are HTML files and specifically line 3 of each file looks like this.



      <TITLE>DATA POPULATION 'CODE on group 1234 by THING'</TITLE>


      I want to grab everything between the single quotes and use that text to rename the file with that text as the filename.



      Can anyone point me down the right path to approach this task? The notion of renaming these one at a time would just be murder.



      Thanks for reading and pondering this problem.










      share|improve this question









      New contributor




      Daniel Cross is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.












      I am trying to devise a solution to rename a large collection of files so that the text in line 3 of each file is the new filename. These files all have the same structure. My scripting ability is poor so I am hoping this problem has been approached before by others so I don't need to invent a new wheel? I've been consulting some sed and awk tutorials but not finding a solution there.



      These are HTML files and specifically line 3 of each file looks like this.



      <TITLE>DATA POPULATION 'CODE on group 1234 by THING'</TITLE>


      I want to grab everything between the single quotes and use that text to rename the file with that text as the filename.



      Can anyone point me down the right path to approach this task? The notion of renaming these one at a time would just be murder.



      Thanks for reading and pondering this problem.







      shell-script rename






      share|improve this question









      New contributor




      Daniel Cross is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.











      share|improve this question









      New contributor




      Daniel Cross is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.









      share|improve this question




      share|improve this question








      edited 18 mins ago









      Stéphane Chazelas

      304k57570927




      304k57570927






      New contributor




      Daniel Cross is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.









      asked 2 hours ago









      Daniel CrossDaniel Cross

      61




      61




      New contributor




      Daniel Cross is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.





      New contributor





      Daniel Cross is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.






      Daniel Cross is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.






















          4 Answers
          4






          active

          oldest

          votes


















          2














          $ awk -v FS="'" -v OFS="t" 'FNR==3 && NF>2 {print FILENAME, $2; nextfile}' *.txt |parallel --colsep "t" 'mv {1} {2}'


          awk iterate over all files in the location. We define the ' as the field separator. Whenever it reaches the third line and there are more than 2 fields (which should be if we have two ') it prints out the filename and the second field (which is the part between the first two ') delimited by a tab. Then it skipes to the next file.



          The result is piped to parallel. parallel execute the mv command by replacing {1} and {2} with values given in the columns from the awk result.



          Some notes:





          • nextfile is not available in all awkversions


          • whitespaces in a filename is never a good idea. You could replace them by an underscore if you change the awk command like this:



            awk -v FS="'" -v OFS="t" 'FNR==3 && NF>2 { gsub(" ", "_", $2); print FILENAME, $2; nextfile}' *.txt



          • You should move or copy your new filenames to another folder. I'm not sure how awk will react if new files appear in the same folder during runtime.






          share|improve this answer

































            1














            for j in ./*.txt
            do
            i=$( sed -n '3p' "$j" | cut -d "'" -f2)
            mv "$j" "$i"
            done


            It will search all the files in the current directory and will move this file to the new one.






            share|improve this answer

































              0














              for src in *.html; do
              { read -r x && read -r x && IFS="'" read -r x dst x; } < "$src" &&
              mv -- "$src" "$dst.html"
              done





              share|improve this answer































                0














                I would do such a thing in perl instead of putting together some slow and fragile tangle of subshells:



                perl -e 'while(<>){
                sub no_rename { print "rename @_n" }
                next unless $. == 3;
                if(my ($f) = /DATA POPULATION +'''(.*?)'''/){
                $f =~ s/[^w]/_/g;
                no_rename $ARGV, $f or warn "rename $ARGV, $f: $!n";
                }
                close ARGV
                }' files ...


                You'll have to change no_rename to rename to make it actually do it, instead of showing it.



                Sorry for the ugly '''; if you put that in a script file instead of one-liner, that should be simply:



                /DATA POPULATION +'(.*?)'/


                If you really want to create filenames with spaces, also add a s after the w in the s///g expression (and similar for other characters that could go in the filename -- by default, the script will replace everything but letters and digits with an underscore).






                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',
                  autoActivateHeartbeat: false,
                  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
                  });


                  }
                  });






                  Daniel Cross is a new contributor. Be nice, and check out our Code of Conduct.










                  draft saved

                  draft discarded


















                  StackExchange.ready(
                  function () {
                  StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f498718%2fscript-to-rename-a-large-number-of-files-using-the-text-in-each-file-to-rename%23new-answer', 'question_page');
                  }
                  );

                  Post as a guest















                  Required, but never shown

























                  4 Answers
                  4






                  active

                  oldest

                  votes








                  4 Answers
                  4






                  active

                  oldest

                  votes









                  active

                  oldest

                  votes






                  active

                  oldest

                  votes









                  2














                  $ awk -v FS="'" -v OFS="t" 'FNR==3 && NF>2 {print FILENAME, $2; nextfile}' *.txt |parallel --colsep "t" 'mv {1} {2}'


                  awk iterate over all files in the location. We define the ' as the field separator. Whenever it reaches the third line and there are more than 2 fields (which should be if we have two ') it prints out the filename and the second field (which is the part between the first two ') delimited by a tab. Then it skipes to the next file.



                  The result is piped to parallel. parallel execute the mv command by replacing {1} and {2} with values given in the columns from the awk result.



                  Some notes:





                  • nextfile is not available in all awkversions


                  • whitespaces in a filename is never a good idea. You could replace them by an underscore if you change the awk command like this:



                    awk -v FS="'" -v OFS="t" 'FNR==3 && NF>2 { gsub(" ", "_", $2); print FILENAME, $2; nextfile}' *.txt



                  • You should move or copy your new filenames to another folder. I'm not sure how awk will react if new files appear in the same folder during runtime.






                  share|improve this answer






























                    2














                    $ awk -v FS="'" -v OFS="t" 'FNR==3 && NF>2 {print FILENAME, $2; nextfile}' *.txt |parallel --colsep "t" 'mv {1} {2}'


                    awk iterate over all files in the location. We define the ' as the field separator. Whenever it reaches the third line and there are more than 2 fields (which should be if we have two ') it prints out the filename and the second field (which is the part between the first two ') delimited by a tab. Then it skipes to the next file.



                    The result is piped to parallel. parallel execute the mv command by replacing {1} and {2} with values given in the columns from the awk result.



                    Some notes:





                    • nextfile is not available in all awkversions


                    • whitespaces in a filename is never a good idea. You could replace them by an underscore if you change the awk command like this:



                      awk -v FS="'" -v OFS="t" 'FNR==3 && NF>2 { gsub(" ", "_", $2); print FILENAME, $2; nextfile}' *.txt



                    • You should move or copy your new filenames to another folder. I'm not sure how awk will react if new files appear in the same folder during runtime.






                    share|improve this answer




























                      2












                      2








                      2







                      $ awk -v FS="'" -v OFS="t" 'FNR==3 && NF>2 {print FILENAME, $2; nextfile}' *.txt |parallel --colsep "t" 'mv {1} {2}'


                      awk iterate over all files in the location. We define the ' as the field separator. Whenever it reaches the third line and there are more than 2 fields (which should be if we have two ') it prints out the filename and the second field (which is the part between the first two ') delimited by a tab. Then it skipes to the next file.



                      The result is piped to parallel. parallel execute the mv command by replacing {1} and {2} with values given in the columns from the awk result.



                      Some notes:





                      • nextfile is not available in all awkversions


                      • whitespaces in a filename is never a good idea. You could replace them by an underscore if you change the awk command like this:



                        awk -v FS="'" -v OFS="t" 'FNR==3 && NF>2 { gsub(" ", "_", $2); print FILENAME, $2; nextfile}' *.txt



                      • You should move or copy your new filenames to another folder. I'm not sure how awk will react if new files appear in the same folder during runtime.






                      share|improve this answer















                      $ awk -v FS="'" -v OFS="t" 'FNR==3 && NF>2 {print FILENAME, $2; nextfile}' *.txt |parallel --colsep "t" 'mv {1} {2}'


                      awk iterate over all files in the location. We define the ' as the field separator. Whenever it reaches the third line and there are more than 2 fields (which should be if we have two ') it prints out the filename and the second field (which is the part between the first two ') delimited by a tab. Then it skipes to the next file.



                      The result is piped to parallel. parallel execute the mv command by replacing {1} and {2} with values given in the columns from the awk result.



                      Some notes:





                      • nextfile is not available in all awkversions


                      • whitespaces in a filename is never a good idea. You could replace them by an underscore if you change the awk command like this:



                        awk -v FS="'" -v OFS="t" 'FNR==3 && NF>2 { gsub(" ", "_", $2); print FILENAME, $2; nextfile}' *.txt



                      • You should move or copy your new filenames to another folder. I'm not sure how awk will react if new files appear in the same folder during runtime.







                      share|improve this answer














                      share|improve this answer



                      share|improve this answer








                      edited 1 hour ago

























                      answered 2 hours ago









                      finswimmerfinswimmer

                      4846




                      4846

























                          1














                          for j in ./*.txt
                          do
                          i=$( sed -n '3p' "$j" | cut -d "'" -f2)
                          mv "$j" "$i"
                          done


                          It will search all the files in the current directory and will move this file to the new one.






                          share|improve this answer






























                            1














                            for j in ./*.txt
                            do
                            i=$( sed -n '3p' "$j" | cut -d "'" -f2)
                            mv "$j" "$i"
                            done


                            It will search all the files in the current directory and will move this file to the new one.






                            share|improve this answer




























                              1












                              1








                              1







                              for j in ./*.txt
                              do
                              i=$( sed -n '3p' "$j" | cut -d "'" -f2)
                              mv "$j" "$i"
                              done


                              It will search all the files in the current directory and will move this file to the new one.






                              share|improve this answer















                              for j in ./*.txt
                              do
                              i=$( sed -n '3p' "$j" | cut -d "'" -f2)
                              mv "$j" "$i"
                              done


                              It will search all the files in the current directory and will move this file to the new one.







                              share|improve this answer














                              share|improve this answer



                              share|improve this answer








                              edited 44 mins ago

























                              answered 2 hours ago









                              PRYPRY

                              1,90431024




                              1,90431024























                                  0














                                  for src in *.html; do
                                  { read -r x && read -r x && IFS="'" read -r x dst x; } < "$src" &&
                                  mv -- "$src" "$dst.html"
                                  done





                                  share|improve this answer




























                                    0














                                    for src in *.html; do
                                    { read -r x && read -r x && IFS="'" read -r x dst x; } < "$src" &&
                                    mv -- "$src" "$dst.html"
                                    done





                                    share|improve this answer


























                                      0












                                      0








                                      0







                                      for src in *.html; do
                                      { read -r x && read -r x && IFS="'" read -r x dst x; } < "$src" &&
                                      mv -- "$src" "$dst.html"
                                      done





                                      share|improve this answer













                                      for src in *.html; do
                                      { read -r x && read -r x && IFS="'" read -r x dst x; } < "$src" &&
                                      mv -- "$src" "$dst.html"
                                      done






                                      share|improve this answer












                                      share|improve this answer



                                      share|improve this answer










                                      answered 20 mins ago









                                      Stéphane ChazelasStéphane Chazelas

                                      304k57570927




                                      304k57570927























                                          0














                                          I would do such a thing in perl instead of putting together some slow and fragile tangle of subshells:



                                          perl -e 'while(<>){
                                          sub no_rename { print "rename @_n" }
                                          next unless $. == 3;
                                          if(my ($f) = /DATA POPULATION +'''(.*?)'''/){
                                          $f =~ s/[^w]/_/g;
                                          no_rename $ARGV, $f or warn "rename $ARGV, $f: $!n";
                                          }
                                          close ARGV
                                          }' files ...


                                          You'll have to change no_rename to rename to make it actually do it, instead of showing it.



                                          Sorry for the ugly '''; if you put that in a script file instead of one-liner, that should be simply:



                                          /DATA POPULATION +'(.*?)'/


                                          If you really want to create filenames with spaces, also add a s after the w in the s///g expression (and similar for other characters that could go in the filename -- by default, the script will replace everything but letters and digits with an underscore).






                                          share|improve this answer






























                                            0














                                            I would do such a thing in perl instead of putting together some slow and fragile tangle of subshells:



                                            perl -e 'while(<>){
                                            sub no_rename { print "rename @_n" }
                                            next unless $. == 3;
                                            if(my ($f) = /DATA POPULATION +'''(.*?)'''/){
                                            $f =~ s/[^w]/_/g;
                                            no_rename $ARGV, $f or warn "rename $ARGV, $f: $!n";
                                            }
                                            close ARGV
                                            }' files ...


                                            You'll have to change no_rename to rename to make it actually do it, instead of showing it.



                                            Sorry for the ugly '''; if you put that in a script file instead of one-liner, that should be simply:



                                            /DATA POPULATION +'(.*?)'/


                                            If you really want to create filenames with spaces, also add a s after the w in the s///g expression (and similar for other characters that could go in the filename -- by default, the script will replace everything but letters and digits with an underscore).






                                            share|improve this answer




























                                              0












                                              0








                                              0







                                              I would do such a thing in perl instead of putting together some slow and fragile tangle of subshells:



                                              perl -e 'while(<>){
                                              sub no_rename { print "rename @_n" }
                                              next unless $. == 3;
                                              if(my ($f) = /DATA POPULATION +'''(.*?)'''/){
                                              $f =~ s/[^w]/_/g;
                                              no_rename $ARGV, $f or warn "rename $ARGV, $f: $!n";
                                              }
                                              close ARGV
                                              }' files ...


                                              You'll have to change no_rename to rename to make it actually do it, instead of showing it.



                                              Sorry for the ugly '''; if you put that in a script file instead of one-liner, that should be simply:



                                              /DATA POPULATION +'(.*?)'/


                                              If you really want to create filenames with spaces, also add a s after the w in the s///g expression (and similar for other characters that could go in the filename -- by default, the script will replace everything but letters and digits with an underscore).






                                              share|improve this answer















                                              I would do such a thing in perl instead of putting together some slow and fragile tangle of subshells:



                                              perl -e 'while(<>){
                                              sub no_rename { print "rename @_n" }
                                              next unless $. == 3;
                                              if(my ($f) = /DATA POPULATION +'''(.*?)'''/){
                                              $f =~ s/[^w]/_/g;
                                              no_rename $ARGV, $f or warn "rename $ARGV, $f: $!n";
                                              }
                                              close ARGV
                                              }' files ...


                                              You'll have to change no_rename to rename to make it actually do it, instead of showing it.



                                              Sorry for the ugly '''; if you put that in a script file instead of one-liner, that should be simply:



                                              /DATA POPULATION +'(.*?)'/


                                              If you really want to create filenames with spaces, also add a s after the w in the s///g expression (and similar for other characters that could go in the filename -- by default, the script will replace everything but letters and digits with an underscore).







                                              share|improve this answer














                                              share|improve this answer



                                              share|improve this answer








                                              edited 16 mins ago

























                                              answered 25 mins ago









                                              pizdelectpizdelect

                                              49716




                                              49716






















                                                  Daniel Cross is a new contributor. Be nice, and check out our Code of Conduct.










                                                  draft saved

                                                  draft discarded


















                                                  Daniel Cross is a new contributor. Be nice, and check out our Code of Conduct.













                                                  Daniel Cross is a new contributor. Be nice, and check out our Code of Conduct.












                                                  Daniel Cross is a new contributor. Be nice, and check out our Code of Conduct.
















                                                  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.




                                                  draft saved


                                                  draft discarded














                                                  StackExchange.ready(
                                                  function () {
                                                  StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f498718%2fscript-to-rename-a-large-number-of-files-using-the-text-in-each-file-to-rename%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

                                                  SQL Server 17 - Attemping to backup to remote NAS but Access is denied

                                                  Always On Availability groups resolving state after failover - Remote harden of transaction...

                                                  Restoring from pg_dump with foreign key constraints