Community
    • Login

    Add line of text to beginning of multiple files

    Scheduled Pinned Locked Moved Help wanted · · · – – – · · ·
    24 Posts 9 Posters 28.4k Views
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • guy038G
      guy038
      last edited by guy038

      Hi, @alan-kilborn and All,

      Indeed, as the \A is not working properly, a lot of particular cases occur and I confess that detailing them all is a bit tedious work !


      • Regarding your first question :

      I don’t see the connection here…where is the dot regex being used?

      The fact of the simple . regex does not match the FF character, of Unicode code-point \x{000C} means that, it is implicitly seen as a non-standard character, i.e. a pseudo EOL character !

      So, from the @Terry-r’s solution (?<!\x0A)^, which can be rewritten as (?<!\n)^, I first added the \r case to the negative look-behind, to handle MAC files and then added the Form Feed character case in case some of these chars are present in current file giving the final form (?<!\n|\r|\f)^

      For instance, assuming the text, below, where three Form Feed chars ( \x{000c} ) are inserted between the strings 12345 and 67890 of the first line

      1234567890
      This is a test
      to verify
      -----><-----
      some oddities
      on this very
      simple text
      
      • Paste this text in a new tab

      • Now, open the Replace dialog

      • SEARCH (?<!\n|\r)^ ( The \f is not present )

      • REPLACE ABC

      • Tick the Wrap around option

      • Select the Regular expression search mode

      • Put the caret, on the line -----><----- between symbols > and <

      • Click on the Replace All button

      You get the text :

      ABC12345ABCABCABC67890
      This is a test
      to verify
      -----><-----
      some oddities
      on this very
      simple text
      

      As you can see, it correctly adds the string ABC at beginning of file, but also after each FF character :-(

      • Now, change the search regex as (?<!\n|\r|\f)^

      • Put the caret, on the line -----><----- between symbols > and <

      • Click on the Replace All button

      This time, we have the expected text, with the string ABC , inserted at beginning if the first line, only ;-))

      ABC1234567890
      This is a test
      to verify
      -----><-----
      some oddities
      on this very
      simple text
      

      So, the 3 syntaxes (?<!\n|\r|\f)^, \^A and also \A^ are correct work-arounds to the bugged \A assertion, used alone !


      Note, Alan, that the syntax \A^ seems a bit more logic than the opposite form ^\A. However, remark that two consecutive assertions are commutative. For instance, the regexes ^$ and $^ are equivalent as, both, searches for a location which is, either, a beginning and an end of lines and match the zero-length location at the beginning of any empty line

      Similarly, two consecutive look-around, which can be considered as user’s assertions, are commutative too ! For instance, the regexes (?-s)(?=ABC)(?=.*XYZ).+ and (?-s)(?=.*XYZ)(?=ABC).+ are equivalent and match any non-null range of chars, beginning with ABC, till the end of current line, if, in addition, the string XYZ occurs from right after ABC till the end of current line !

      I hope that these lines answer to your third question :

      I understand why the earlier (?<!\x0A)^ or (?<!\n|\r|\f)^ work, but ^\A is hard to get one’s head around

      Now, contrary to the 3 correct regex syntaxes, above, the initial regex S/R, against our sample text :

      SEARCH \A

      REPLACE ABC

      gives the complete mess, below, adding the string ABC after any existing character :-((

      ABC1ABC2ABC3ABC4ABC5ABCABCABCABC6ABC7ABC8ABC9ABC0ABC
      ABCTABChABCiABCsABC ABCiABCsABC ABCaABC ABCtABCeABCsABCtABC
      ABCtABCoABC ABCvABCeABCrABCiABCfABCyABC
      ABC-ABC-ABC-ABC-ABC-ABC>ABC<ABC-ABC-ABC-ABC-ABC-ABC
      ABCsABCoABCmABCeABC ABCoABCdABCdABCiABCtABCiABCeABCsABC
      ABCoABCnABC ABCtABChABCiABCsABC ABCvABCeABCrABCyABC
      ABCsABCiABCmABCpABClABCeABC ABCtABCeABCxABCtABC
      ABC
      

      Now, regarding your second question :

      I’m not sure I’m following this, either.

      How about some real examples that you are usually so good at? :-)

      Well, if we still assume our sample text :

      1234567890
      This is a test
      to verify
      -----><-----
      some oddities
      on this very
      simple text
      

      Let’s use, now, the following regex S/R, with Wrap around, Regular expression set and the caret between the >< string :

      SEARCH \A^

      REPLACE ABC\r\n ( Note that we add some EOL chars, at the end of the replacement regex )

      As expected, after clicking on the Replace All button, we obtain the text, with the line ABC inserted before the present first line

      ABC
      1234567890
      This is a test
      to verify
      -----><-----
      some oddities
      on this very
      simple text
      
      • Now, hit Ctrl + Z to undo the changes

      • Hit 3 times on the Enter key, to create three empty lines, beginning current file

      • Re-run the same S/R

      This time, we get :

      ABC
      
      ABC
      
      ABC
      
      ABC
      1234567890
      This is a test
      to verify
      -----><-----
      some oddities
      on this very
      simple text
      

      Which is not, obviously, what it is expected ! This is the reason why I said :

      • In case of your replacement regex ends with the forms \r\n, \n or \r, depending of your file(s) structure, as above, the file(s) must not begin with one/several true empty lines !

      Finally :

      • Hit, again, Ctrl + Z to undo the changes

      • Use the logical regex S/R, below, with \A, against our sample text, with the first three empty lines :

      SEARCH \A

      REPLACE ABC\r\n

      This time, it’s even worse ! As you can see, below , everything seems to go wrong for all ;-(((

      ABC
      
      ABC
      
      ABC
      
      ABC
      1ABC
      2ABC
      3ABC
      4ABC
      5ABC
      ABC
      ABC
      ABC
      6ABC
      7ABC
      8ABC
      9ABC
      0ABC
      
      ABC
      TABC
      hABC
      iABC
      sABC
       ABC
      iABC
      sABC
       ABC
      aABC
       ABC
      tABC
      eABC
      sABC
      tABC
      
      ABC
      tABC
      oABC
       ABC
      vABC
      eABC
      rABC
      iABC
      fABC
      yABC
      
      ABC
      -ABC
      -ABC
      -ABC
      -ABC
      -ABC
      >ABC
      <ABC
      -ABC
      -ABC
      -ABC
      -ABC
      -ABC
      
      ABC
      sABC
      oABC
      mABC
      eABC
       ABC
      oABC
      dABC
      dABC
      iABC
      tABC
      iABC
      eABC
      sABC
      
      ABC
      oABC
      nABC
       ABC
      tABC
      hABC
      iABC
      sABC
       ABC
      vABC
      eABC
      rABC
      yABC
      
      ABC
      sABC
      iABC
      mABC
      pABC
      lABC
      eABC
       ABC
      tABC
      eABC
      xABC
      tABC
      
      ABC
      

      Best Regards,

      guy038

      1 Reply Last reply Reply Quote 2
      • Alan KilbornA
        Alan Kilborn
        last edited by

        @guy038 said in Add line of text to beginning of multiple files:

        In case of your replacement regex ends with the forms \r\n, \n or \r, depending of your file(s) structure, as above, it/they must not begin with one/several true empty lines !

        So I found myself with just such a case. Hmmm, what to do…?

        Here’s what I wanted:

        • Add new first line\r\n to a bunch of files as, obviously, the new first line data.

        Here’s what I did:

        I did a two-step replacement; first I did:

        Find what box: ^\A
        Replace with box: new first lineFIRSTLINEPSEUDOENDING

        Secondly,

        Find what box: FIRSTLINEPSEUDOENDING
        Replace with box: \r\n

        Of course FIRSTLINEPSEUDOENDING could be any unique string that doesn’t already appear in the files I’m applying this to.

        1 Reply Last reply Reply Quote 2
        • sean o sullivanS
          sean o sullivan
          last edited by

          Hi All,

          i’m trying to add the below 6 lines into the top of 300 batch scripts, but none of the above worked

          @echo off
          call D:\Tidal\bin\SetupEnv.bat
          if errorlevel 1 (
          echo Could not retrieve environment variables.
          exit /b 1
          )

          Alan KilbornA 1 Reply Last reply Reply Quote 0
          • Alan KilbornA
            Alan Kilborn @sean o sullivan
            last edited by

            @sean-o-sullivan said in Add line of text to beginning of multiple files:

            none of the above worked

            What exactly did you try?

            Additional question: Do all/some/none of the files you want to affect have empty line(s) at the beginning?

            1 Reply Last reply Reply Quote 1
            • PeterJonesP
              PeterJones
              last edited by

              @sean-o-sullivan,

              none of the above worked

              Notepad++ search/replace boxes use a single line for inputting the expression, so if you want to insert multiple lines, you have to encode the line endings in a way the search engine understands: since you are likely using Windows CRLF line endings for a batch file, every newline in the text you want to insert needs to be converted to \r\n; further, any special character (like the \) needs to be escaped. So, to give an example, the first two lines of your insertion would be something like @echo off\r\ncall D:\\Tidal\\bin\\SetupEnv.bat\r\n, and you’d have to prepare the rest of the lines similarly.

              But really, when you’re getting to multi-line-text inserts and hundreds of files, you’re starting to move beyond what is the primary focus of text editor software: it focuses more on one or a few files, rather than bulk editing (though Find in Files is a nice move toward bulk-file-editing).

              Operating systems like Windows and Linux are primarily GUI nowadays, but they still ship with one or more command line systems; there’s a reason for that: you can do powerful things at the command line, often on lots of files in a short amount of time, with very little code.

              1. Backup any critical batch files: your files are always your responsibility
              2. Create a file called prefix.in, which has your 6 lines that you want to insert (make sure to have a NEWLINE at the end of the last line), and save.
              3. Put prefix.in in the same directory as the three-hundred *.bat files
              4. open cmd.exe and change to that directory
              5. for %F in (*.bat) do @( copy prefix.in + %F %F.out & move /Y %F.out %F )

              This will look up the name (%F) of every batch file in the folder, it will concatenate the contents of prefix.in and %F into a new temporary file %F.out, then it will rename %F.out back to %F. (I would have used REN or RENAME instead of MOVE, but REN doesn’t have the /Y to force allowing overwriting of the destination.)

              With one line of command-line syntax, I just prefixed all 300 batch files with the 6 lines you wanted.

              (Whenever I need to look up cmd.exe syntax, I use https://ss64.com/nt/syntax.html for topic-level, and the “CMD” link https://ss64.com/nt/ for a per-commmand reference. I know, using cmd.exe is old fashioned, but I’ve never gotten the hang of powershell.)

              Notepad++ is great, but there are other tools available to you.

              Alan KilbornA 1 Reply Last reply Reply Quote 2
              • Alan KilbornA
                Alan Kilborn @PeterJones
                last edited by Alan Kilborn

                @PeterJones does the legwork I was trying to get the OP to do. :-(

                I think it’s an OK task for Notepad++. A lot of people are scared to dip down into the world of batch/CMD/Powershell…

                The OP even did the research to find this thread. However, the OP should have done more than “Wah! It doesn’t work”. Not a direct quotation. :-)

                Notepad++ …/replace boxes use a single line for inputting the expression, so if you want to insert multiple lines, you have to encode the line endings in a way the search engine understands: since you are likely using Windows CRLF line endings for a batch file, every newline in the text you want to insert needs to be converted to \r\n; further, any special character (like the ) needs to be escaped.

                People are scared also to do Pythonscript, so I hesitate to bring this up, but a script I use can do the conversion of the data per the above. It takes the currently selected text, formats it correctly, and puts the result in the clipboard, ready for pasting into the Replace with box:

                # -*- coding: utf-8 -*-
                
                from Npp import editor, notepad
                
                class T11987(object):
                    def __init__(self):
                        if editor.getSelections() > 1: return  # acting on multiple selections or a column block probably doesn't make sense
                        s = editor.getSelText()
                        if len(s) == 0: return
                        new_s = s.replace('\\', '\\\\').replace('\r', '\\r').replace('\n', '\\n').replace('(', '\\(').replace(')', '\\)')
                        if len(new_s) > 2046:
                            notepad.messageBox('After conversion, the selected text is too long for the ***Replace with*** box (limit: ~2046 chars)', '')
                        else:
                            editor.copyText(new_s)
                            notepad.messageBox('The selected text has been converted and is now in the clipboard.', '')
                
                if __name__ == '__main__': T11987()
                

                Running the script on the OP’s replace data yields the full string that Peter started:

                @echo off\r\ncall D:\\Tidal\\bin\\SetupEnv.bat\r\nif errorlevel 1 \(\r\necho Could not retrieve environment variables.\r\nexit /b 1\r\n\)\r\n

                There might be more characters that need escaping in a regex replace string, but in practice I haven’t encountered them yet.

                Alan KilbornA 1 Reply Last reply Reply Quote 2
                • sean o sullivanS
                  sean o sullivan
                  last edited by

                  @PeterJones You sir are a legend, that worked perfectly!!! Thank you so much for taking the time to help me out

                  1 Reply Last reply Reply Quote 3
                  • Alan KilbornA
                    Alan Kilborn @Alan Kilborn
                    last edited by

                    A lot of people are scared to dip down into the world of batch/CMD/Powershell…

                    @PeterJones You sir are a legend, that worked perfectly!!!

                    …and some people are not afraid. :-)

                    One point of clarification on my previous reply:

                    @PeterJones had previously stated:

                    Notepad++ search/replace boxes use a single line for inputting the expression

                    but my reply concentrated only on the replace box. The reason for that is that if you want to get multiline text that you already have in the Notepad++ window into the “search box”, all you have to do is select it and press ctrl+f (if ctrl+f is so configured – to copy into the box automatically). No conversion of the text (or escaping) is necessary.

                    UNLESS, you are going to be doing a multiline replacement – in which case you need to be in Regular expression search mode – and your search data contains any of the special regex metacharacters. In this case the best thing to do might be to add a \Q at the very start of the “search box”.

                    Yikes, this might be really “obscure”!

                    1 Reply Last reply Reply Quote 1
                    • PeterJonesP
                      PeterJones
                      last edited by

                      @sean-o-sullivan ,

                      Glad you got something that worked. I hope you took the opportunity to learn from what @Alan-Kilborn shared as well, because it really is helpful search/replace advice, too.

                      -----

                      @Alan-Kilborn said in Add line of text to beginning of multiple files:

                      I think it’s an OK task for Notepad++.

                      Well, the 6 lines aren’t bad to encode into the replace box. But when the next poster wants to insert 1023 lines at the beginning of every config file? As I said, “you’re starting to move beyond” (emphasis added): inserting 6 lines at the beginning of 300 files has started down the slippery slope out of the realm of pure text-editor, but not so far that it’s not doable.

                      Pythonscript, … It takes the currently selected text, formats it correctly, and puts the result in the clipboard, ready for pasting into the Replace with box

                      I didn’t read correctly / realize what you were doing there until the second read: that’s just cool.

                      A side question, unrelated to OP: why create an object with the __init__, rather than just have a T11987() function instead?

                      my reply concentrated only on the replace box. … No conversion … necessary

                      True enough.

                      Alan KilbornA 1 Reply Last reply Reply Quote 0
                      • Alan KilbornA
                        Alan Kilborn @PeterJones
                        last edited by

                        @PeterJones said in Add line of text to beginning of multiple files:

                        inserting 6 lines at the beginning of 300 files has started down the slippery slope out of the realm of pure text-editor

                        Agreed. Maybe that’s why I said it’s an “OK” task for Notepad++ and not “a great” task. :-)

                        why create an object with the init, rather than just have a T11987() function instead?

                        It’s just my new framework for scripts (I copy from some boilerplate when I make a new script). Obviously in this case it is fairly trivial, but in scripts that use callbacks a object-based approach has bigger benefits. I picked up on this by observing how @Ekopalypse does some of the more complicated scripts he’s presented. BTW, I picked up on using the topic/posting id in the name of a script/function/class from YOU. :-)

                        1 Reply Last reply Reply Quote 1
                        • First post
                          Last post
                        The Community of users of the Notepad++ text editor.
                        Powered by NodeBB | Contributors