How to prepend multiple lines to a file












1















In the question How to append multiple lines to a file the OP was seeking a way to append multiple lines to a file within the shell. The solution:



cat <<EOT >> test.txt
line 1
line 2
EOT


I want to prepend lines and my attempt looks like:



echo 3 >test.text
cat test.text <<EOT >> test.text
1
2
EOT


But this results in an error:



cat: test.text: input file is output file


EDIT: for clarification, I am following a long server setup guide with instructions to manually edit configuration files. Editing at times involves prepending blocks of text to a file. In automating some of the steps, I want to retain the verbosity of the command by copying the text from the guide as-is and putting into a bash one-liner. For this reason the multi-line text input using EOT is preferred.



EDIT: other answers using sed require backslashes to be appended to the end of each line but I want to enter multiple lines without modification.



Is there a way to prepend multiple lines to a file in a similar fashion above (ideally without a temporary file and installing moreutils)?










share|improve this question

























  • The reason that this is a problem is because it is the shell that does all the redirection work before starting cat (but without reading or writing anything yet) and it can detect that you will overwrite your file and gives an error. The solution is to use a program that can rewrite a file (perl -i comes to mind) and not the shell.

    – Thorbjørn Ravn Andersen
    yesterday











  • It seems to me that this answer unix.stackexchange.com/a/99351/117549 achieves that goal...?

    – Jeff Schaller
    yesterday











  • Thanks @JeffSchaller, but not quite as It fails for multiline entries. Please see the output at: imgur.com/a/XfvfDjH

    – user1330734
    17 hours ago






  • 1





    All the solutions given here or to the duplicate Q are using temporary files. That being said, Jeff Schaller's post now includes a solution that does exactly what you want: it inserts the text as-is via a here-document.

    – don_crissti
    12 hours ago











  • @don_crissti Jeff's updated answer is what I was looking for 👍 I was not familiar with here documents before.

    – user1330734
    3 hours ago


















1















In the question How to append multiple lines to a file the OP was seeking a way to append multiple lines to a file within the shell. The solution:



cat <<EOT >> test.txt
line 1
line 2
EOT


I want to prepend lines and my attempt looks like:



echo 3 >test.text
cat test.text <<EOT >> test.text
1
2
EOT


But this results in an error:



cat: test.text: input file is output file


EDIT: for clarification, I am following a long server setup guide with instructions to manually edit configuration files. Editing at times involves prepending blocks of text to a file. In automating some of the steps, I want to retain the verbosity of the command by copying the text from the guide as-is and putting into a bash one-liner. For this reason the multi-line text input using EOT is preferred.



EDIT: other answers using sed require backslashes to be appended to the end of each line but I want to enter multiple lines without modification.



Is there a way to prepend multiple lines to a file in a similar fashion above (ideally without a temporary file and installing moreutils)?










share|improve this question

























  • The reason that this is a problem is because it is the shell that does all the redirection work before starting cat (but without reading or writing anything yet) and it can detect that you will overwrite your file and gives an error. The solution is to use a program that can rewrite a file (perl -i comes to mind) and not the shell.

    – Thorbjørn Ravn Andersen
    yesterday











  • It seems to me that this answer unix.stackexchange.com/a/99351/117549 achieves that goal...?

    – Jeff Schaller
    yesterday











  • Thanks @JeffSchaller, but not quite as It fails for multiline entries. Please see the output at: imgur.com/a/XfvfDjH

    – user1330734
    17 hours ago






  • 1





    All the solutions given here or to the duplicate Q are using temporary files. That being said, Jeff Schaller's post now includes a solution that does exactly what you want: it inserts the text as-is via a here-document.

    – don_crissti
    12 hours ago











  • @don_crissti Jeff's updated answer is what I was looking for 👍 I was not familiar with here documents before.

    – user1330734
    3 hours ago
















1












1








1


0






In the question How to append multiple lines to a file the OP was seeking a way to append multiple lines to a file within the shell. The solution:



cat <<EOT >> test.txt
line 1
line 2
EOT


I want to prepend lines and my attempt looks like:



echo 3 >test.text
cat test.text <<EOT >> test.text
1
2
EOT


But this results in an error:



cat: test.text: input file is output file


EDIT: for clarification, I am following a long server setup guide with instructions to manually edit configuration files. Editing at times involves prepending blocks of text to a file. In automating some of the steps, I want to retain the verbosity of the command by copying the text from the guide as-is and putting into a bash one-liner. For this reason the multi-line text input using EOT is preferred.



EDIT: other answers using sed require backslashes to be appended to the end of each line but I want to enter multiple lines without modification.



Is there a way to prepend multiple lines to a file in a similar fashion above (ideally without a temporary file and installing moreutils)?










share|improve this question
















In the question How to append multiple lines to a file the OP was seeking a way to append multiple lines to a file within the shell. The solution:



cat <<EOT >> test.txt
line 1
line 2
EOT


I want to prepend lines and my attempt looks like:



echo 3 >test.text
cat test.text <<EOT >> test.text
1
2
EOT


But this results in an error:



cat: test.text: input file is output file


EDIT: for clarification, I am following a long server setup guide with instructions to manually edit configuration files. Editing at times involves prepending blocks of text to a file. In automating some of the steps, I want to retain the verbosity of the command by copying the text from the guide as-is and putting into a bash one-liner. For this reason the multi-line text input using EOT is preferred.



EDIT: other answers using sed require backslashes to be appended to the end of each line but I want to enter multiple lines without modification.



Is there a way to prepend multiple lines to a file in a similar fashion above (ideally without a temporary file and installing moreutils)?







text-processing files






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 12 hours ago









don_crissti

50.6k15134163




50.6k15134163










asked yesterday









user1330734user1330734

77118




77118













  • The reason that this is a problem is because it is the shell that does all the redirection work before starting cat (but without reading or writing anything yet) and it can detect that you will overwrite your file and gives an error. The solution is to use a program that can rewrite a file (perl -i comes to mind) and not the shell.

    – Thorbjørn Ravn Andersen
    yesterday











  • It seems to me that this answer unix.stackexchange.com/a/99351/117549 achieves that goal...?

    – Jeff Schaller
    yesterday











  • Thanks @JeffSchaller, but not quite as It fails for multiline entries. Please see the output at: imgur.com/a/XfvfDjH

    – user1330734
    17 hours ago






  • 1





    All the solutions given here or to the duplicate Q are using temporary files. That being said, Jeff Schaller's post now includes a solution that does exactly what you want: it inserts the text as-is via a here-document.

    – don_crissti
    12 hours ago











  • @don_crissti Jeff's updated answer is what I was looking for 👍 I was not familiar with here documents before.

    – user1330734
    3 hours ago





















  • The reason that this is a problem is because it is the shell that does all the redirection work before starting cat (but without reading or writing anything yet) and it can detect that you will overwrite your file and gives an error. The solution is to use a program that can rewrite a file (perl -i comes to mind) and not the shell.

    – Thorbjørn Ravn Andersen
    yesterday











  • It seems to me that this answer unix.stackexchange.com/a/99351/117549 achieves that goal...?

    – Jeff Schaller
    yesterday











  • Thanks @JeffSchaller, but not quite as It fails for multiline entries. Please see the output at: imgur.com/a/XfvfDjH

    – user1330734
    17 hours ago






  • 1





    All the solutions given here or to the duplicate Q are using temporary files. That being said, Jeff Schaller's post now includes a solution that does exactly what you want: it inserts the text as-is via a here-document.

    – don_crissti
    12 hours ago











  • @don_crissti Jeff's updated answer is what I was looking for 👍 I was not familiar with here documents before.

    – user1330734
    3 hours ago



















The reason that this is a problem is because it is the shell that does all the redirection work before starting cat (but without reading or writing anything yet) and it can detect that you will overwrite your file and gives an error. The solution is to use a program that can rewrite a file (perl -i comes to mind) and not the shell.

– Thorbjørn Ravn Andersen
yesterday





The reason that this is a problem is because it is the shell that does all the redirection work before starting cat (but without reading or writing anything yet) and it can detect that you will overwrite your file and gives an error. The solution is to use a program that can rewrite a file (perl -i comes to mind) and not the shell.

– Thorbjørn Ravn Andersen
yesterday













It seems to me that this answer unix.stackexchange.com/a/99351/117549 achieves that goal...?

– Jeff Schaller
yesterday





It seems to me that this answer unix.stackexchange.com/a/99351/117549 achieves that goal...?

– Jeff Schaller
yesterday













Thanks @JeffSchaller, but not quite as It fails for multiline entries. Please see the output at: imgur.com/a/XfvfDjH

– user1330734
17 hours ago





Thanks @JeffSchaller, but not quite as It fails for multiline entries. Please see the output at: imgur.com/a/XfvfDjH

– user1330734
17 hours ago




1




1





All the solutions given here or to the duplicate Q are using temporary files. That being said, Jeff Schaller's post now includes a solution that does exactly what you want: it inserts the text as-is via a here-document.

– don_crissti
12 hours ago





All the solutions given here or to the duplicate Q are using temporary files. That being said, Jeff Schaller's post now includes a solution that does exactly what you want: it inserts the text as-is via a here-document.

– don_crissti
12 hours ago













@don_crissti Jeff's updated answer is what I was looking for 👍 I was not familiar with here documents before.

– user1330734
3 hours ago







@don_crissti Jeff's updated answer is what I was looking for 👍 I was not familiar with here documents before.

– user1330734
3 hours ago












4 Answers
4






active

oldest

votes


















4














If you need to read in the output of a command, you could use ed as in the linked question, with this variation:



ed -s test.txt <<< $'0r !echo stuffnwnq'


This reads the output of the command echo stuff into test.txt after line zero.





To insert multi-line text before the 1st line via here-doc you'd run



ed -s test.txt <<EOT
1i
add some line
and some more
to the beginning
.
w
q
EOT


The dot signals the end of input-mode which means the last solution assumes your text doesn't contain lines consisting of single dots.






share|improve this answer

































    3














    You can use the plain ol' ex text editor which should be available in almost all POSIX comliant systems.



    To insert in the first line you just do



    ex -sc '1i|new first line' -cx test.txt


    For the case of multiple lines to be added, just add the lines in a loop, with the top most element to be added at the last (like a stack)



    for number in 5 4 3 2 1; do
    ex -sc '1i|'"$number"'' -cx newfile
    done


    of if you want to avoid multiple file write operations on the file, construct a variable with the multi-line content and insert it directly



    multiple_lines=$'line1nline2nline3nline4nline5n'
    ex -sc '1i|'"$multiple_lines"'' -cx newfile





    share|improve this answer

































      3














      The safest way to do this would be to copy the original file to a temporary location, and the concatenate the new contents with that file into the old name:



      tmpfile=$(mktemp)

      cp myfile "$tmpfile" &&
      cat - "$tmpfile" <<NEW_CONTENTS >myfile
      this is
      new contents
      at top of file
      NEW_CONTENTS

      rm "$tmpfile"


      Notice that the cat command itself is almost the same as your



      cat myfile <<EOT >>myfile
      1
      2
      3
      EOT


      However, cat has to be told to also read its standard input, which it does when one of its filename operands is -. We also can't redirect from the original file and then append the result to the same file, as that creates a loop that would make the file grow until it fills all space on the partition. This is why I first copy the file to a temporary file and then use that to create new contents for the old name.



      We could also have done



      tmpfile=$(mktemp)

      cat - myfile <<NEW_CONTENTS >"$tmpfile" &&
      this is
      new contents
      at top of file
      NEW_CONTENTS
      mv "$tmpfile" myfile


      I.e., write the result to a temporary file and then move that so that it replaces the original. This order of operations is however not guaranteed to preserve ownerships and permissions on myfile.





      A small shell function that takes standard input and places it atop a given filename:



      paste_header () {
      local tmpfile=$(mktemp)

      trap "rm -f '$tmpfile'" EXIT

      cat - "$1" >"$tmpfile" &&
      cat "$tmpfile" >"$1"
      }


      The way this is written, it would allow the user to, for example, paste in contents from the clipboard interactively, but would not modify the original file if the input was interrupted by Ctrl+C. The interactive input would need to be terminated by pressing Ctrl+D (which sends EOT, i.e. end-of-text).



      The function would be used as



      paste_header filename


      to interactively paste data to be added into filename (end input with Ctrl+D).



      or



      paste_header filename <otherfile


      to insert data from another file.






      share|improve this answer

































        0














        Using sed:



        $ sed -e 'i1' -e 'i2' test.text
        1
        2
        3





        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
          });


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f497141%2fhow-to-prepend-multiple-lines-to-a-file%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









          4














          If you need to read in the output of a command, you could use ed as in the linked question, with this variation:



          ed -s test.txt <<< $'0r !echo stuffnwnq'


          This reads the output of the command echo stuff into test.txt after line zero.





          To insert multi-line text before the 1st line via here-doc you'd run



          ed -s test.txt <<EOT
          1i
          add some line
          and some more
          to the beginning
          .
          w
          q
          EOT


          The dot signals the end of input-mode which means the last solution assumes your text doesn't contain lines consisting of single dots.






          share|improve this answer






























            4














            If you need to read in the output of a command, you could use ed as in the linked question, with this variation:



            ed -s test.txt <<< $'0r !echo stuffnwnq'


            This reads the output of the command echo stuff into test.txt after line zero.





            To insert multi-line text before the 1st line via here-doc you'd run



            ed -s test.txt <<EOT
            1i
            add some line
            and some more
            to the beginning
            .
            w
            q
            EOT


            The dot signals the end of input-mode which means the last solution assumes your text doesn't contain lines consisting of single dots.






            share|improve this answer




























              4












              4








              4







              If you need to read in the output of a command, you could use ed as in the linked question, with this variation:



              ed -s test.txt <<< $'0r !echo stuffnwnq'


              This reads the output of the command echo stuff into test.txt after line zero.





              To insert multi-line text before the 1st line via here-doc you'd run



              ed -s test.txt <<EOT
              1i
              add some line
              and some more
              to the beginning
              .
              w
              q
              EOT


              The dot signals the end of input-mode which means the last solution assumes your text doesn't contain lines consisting of single dots.






              share|improve this answer















              If you need to read in the output of a command, you could use ed as in the linked question, with this variation:



              ed -s test.txt <<< $'0r !echo stuffnwnq'


              This reads the output of the command echo stuff into test.txt after line zero.





              To insert multi-line text before the 1st line via here-doc you'd run



              ed -s test.txt <<EOT
              1i
              add some line
              and some more
              to the beginning
              .
              w
              q
              EOT


              The dot signals the end of input-mode which means the last solution assumes your text doesn't contain lines consisting of single dots.







              share|improve this answer














              share|improve this answer



              share|improve this answer








              edited 12 hours ago









              don_crissti

              50.6k15134163




              50.6k15134163










              answered yesterday









              Jeff SchallerJeff Schaller

              40.4k1054126




              40.4k1054126

























                  3














                  You can use the plain ol' ex text editor which should be available in almost all POSIX comliant systems.



                  To insert in the first line you just do



                  ex -sc '1i|new first line' -cx test.txt


                  For the case of multiple lines to be added, just add the lines in a loop, with the top most element to be added at the last (like a stack)



                  for number in 5 4 3 2 1; do
                  ex -sc '1i|'"$number"'' -cx newfile
                  done


                  of if you want to avoid multiple file write operations on the file, construct a variable with the multi-line content and insert it directly



                  multiple_lines=$'line1nline2nline3nline4nline5n'
                  ex -sc '1i|'"$multiple_lines"'' -cx newfile





                  share|improve this answer






























                    3














                    You can use the plain ol' ex text editor which should be available in almost all POSIX comliant systems.



                    To insert in the first line you just do



                    ex -sc '1i|new first line' -cx test.txt


                    For the case of multiple lines to be added, just add the lines in a loop, with the top most element to be added at the last (like a stack)



                    for number in 5 4 3 2 1; do
                    ex -sc '1i|'"$number"'' -cx newfile
                    done


                    of if you want to avoid multiple file write operations on the file, construct a variable with the multi-line content and insert it directly



                    multiple_lines=$'line1nline2nline3nline4nline5n'
                    ex -sc '1i|'"$multiple_lines"'' -cx newfile





                    share|improve this answer




























                      3












                      3








                      3







                      You can use the plain ol' ex text editor which should be available in almost all POSIX comliant systems.



                      To insert in the first line you just do



                      ex -sc '1i|new first line' -cx test.txt


                      For the case of multiple lines to be added, just add the lines in a loop, with the top most element to be added at the last (like a stack)



                      for number in 5 4 3 2 1; do
                      ex -sc '1i|'"$number"'' -cx newfile
                      done


                      of if you want to avoid multiple file write operations on the file, construct a variable with the multi-line content and insert it directly



                      multiple_lines=$'line1nline2nline3nline4nline5n'
                      ex -sc '1i|'"$multiple_lines"'' -cx newfile





                      share|improve this answer















                      You can use the plain ol' ex text editor which should be available in almost all POSIX comliant systems.



                      To insert in the first line you just do



                      ex -sc '1i|new first line' -cx test.txt


                      For the case of multiple lines to be added, just add the lines in a loop, with the top most element to be added at the last (like a stack)



                      for number in 5 4 3 2 1; do
                      ex -sc '1i|'"$number"'' -cx newfile
                      done


                      of if you want to avoid multiple file write operations on the file, construct a variable with the multi-line content and insert it directly



                      multiple_lines=$'line1nline2nline3nline4nline5n'
                      ex -sc '1i|'"$multiple_lines"'' -cx newfile






                      share|improve this answer














                      share|improve this answer



                      share|improve this answer








                      edited yesterday

























                      answered yesterday









                      InianInian

                      4,055824




                      4,055824























                          3














                          The safest way to do this would be to copy the original file to a temporary location, and the concatenate the new contents with that file into the old name:



                          tmpfile=$(mktemp)

                          cp myfile "$tmpfile" &&
                          cat - "$tmpfile" <<NEW_CONTENTS >myfile
                          this is
                          new contents
                          at top of file
                          NEW_CONTENTS

                          rm "$tmpfile"


                          Notice that the cat command itself is almost the same as your



                          cat myfile <<EOT >>myfile
                          1
                          2
                          3
                          EOT


                          However, cat has to be told to also read its standard input, which it does when one of its filename operands is -. We also can't redirect from the original file and then append the result to the same file, as that creates a loop that would make the file grow until it fills all space on the partition. This is why I first copy the file to a temporary file and then use that to create new contents for the old name.



                          We could also have done



                          tmpfile=$(mktemp)

                          cat - myfile <<NEW_CONTENTS >"$tmpfile" &&
                          this is
                          new contents
                          at top of file
                          NEW_CONTENTS
                          mv "$tmpfile" myfile


                          I.e., write the result to a temporary file and then move that so that it replaces the original. This order of operations is however not guaranteed to preserve ownerships and permissions on myfile.





                          A small shell function that takes standard input and places it atop a given filename:



                          paste_header () {
                          local tmpfile=$(mktemp)

                          trap "rm -f '$tmpfile'" EXIT

                          cat - "$1" >"$tmpfile" &&
                          cat "$tmpfile" >"$1"
                          }


                          The way this is written, it would allow the user to, for example, paste in contents from the clipboard interactively, but would not modify the original file if the input was interrupted by Ctrl+C. The interactive input would need to be terminated by pressing Ctrl+D (which sends EOT, i.e. end-of-text).



                          The function would be used as



                          paste_header filename


                          to interactively paste data to be added into filename (end input with Ctrl+D).



                          or



                          paste_header filename <otherfile


                          to insert data from another file.






                          share|improve this answer






























                            3














                            The safest way to do this would be to copy the original file to a temporary location, and the concatenate the new contents with that file into the old name:



                            tmpfile=$(mktemp)

                            cp myfile "$tmpfile" &&
                            cat - "$tmpfile" <<NEW_CONTENTS >myfile
                            this is
                            new contents
                            at top of file
                            NEW_CONTENTS

                            rm "$tmpfile"


                            Notice that the cat command itself is almost the same as your



                            cat myfile <<EOT >>myfile
                            1
                            2
                            3
                            EOT


                            However, cat has to be told to also read its standard input, which it does when one of its filename operands is -. We also can't redirect from the original file and then append the result to the same file, as that creates a loop that would make the file grow until it fills all space on the partition. This is why I first copy the file to a temporary file and then use that to create new contents for the old name.



                            We could also have done



                            tmpfile=$(mktemp)

                            cat - myfile <<NEW_CONTENTS >"$tmpfile" &&
                            this is
                            new contents
                            at top of file
                            NEW_CONTENTS
                            mv "$tmpfile" myfile


                            I.e., write the result to a temporary file and then move that so that it replaces the original. This order of operations is however not guaranteed to preserve ownerships and permissions on myfile.





                            A small shell function that takes standard input and places it atop a given filename:



                            paste_header () {
                            local tmpfile=$(mktemp)

                            trap "rm -f '$tmpfile'" EXIT

                            cat - "$1" >"$tmpfile" &&
                            cat "$tmpfile" >"$1"
                            }


                            The way this is written, it would allow the user to, for example, paste in contents from the clipboard interactively, but would not modify the original file if the input was interrupted by Ctrl+C. The interactive input would need to be terminated by pressing Ctrl+D (which sends EOT, i.e. end-of-text).



                            The function would be used as



                            paste_header filename


                            to interactively paste data to be added into filename (end input with Ctrl+D).



                            or



                            paste_header filename <otherfile


                            to insert data from another file.






                            share|improve this answer




























                              3












                              3








                              3







                              The safest way to do this would be to copy the original file to a temporary location, and the concatenate the new contents with that file into the old name:



                              tmpfile=$(mktemp)

                              cp myfile "$tmpfile" &&
                              cat - "$tmpfile" <<NEW_CONTENTS >myfile
                              this is
                              new contents
                              at top of file
                              NEW_CONTENTS

                              rm "$tmpfile"


                              Notice that the cat command itself is almost the same as your



                              cat myfile <<EOT >>myfile
                              1
                              2
                              3
                              EOT


                              However, cat has to be told to also read its standard input, which it does when one of its filename operands is -. We also can't redirect from the original file and then append the result to the same file, as that creates a loop that would make the file grow until it fills all space on the partition. This is why I first copy the file to a temporary file and then use that to create new contents for the old name.



                              We could also have done



                              tmpfile=$(mktemp)

                              cat - myfile <<NEW_CONTENTS >"$tmpfile" &&
                              this is
                              new contents
                              at top of file
                              NEW_CONTENTS
                              mv "$tmpfile" myfile


                              I.e., write the result to a temporary file and then move that so that it replaces the original. This order of operations is however not guaranteed to preserve ownerships and permissions on myfile.





                              A small shell function that takes standard input and places it atop a given filename:



                              paste_header () {
                              local tmpfile=$(mktemp)

                              trap "rm -f '$tmpfile'" EXIT

                              cat - "$1" >"$tmpfile" &&
                              cat "$tmpfile" >"$1"
                              }


                              The way this is written, it would allow the user to, for example, paste in contents from the clipboard interactively, but would not modify the original file if the input was interrupted by Ctrl+C. The interactive input would need to be terminated by pressing Ctrl+D (which sends EOT, i.e. end-of-text).



                              The function would be used as



                              paste_header filename


                              to interactively paste data to be added into filename (end input with Ctrl+D).



                              or



                              paste_header filename <otherfile


                              to insert data from another file.






                              share|improve this answer















                              The safest way to do this would be to copy the original file to a temporary location, and the concatenate the new contents with that file into the old name:



                              tmpfile=$(mktemp)

                              cp myfile "$tmpfile" &&
                              cat - "$tmpfile" <<NEW_CONTENTS >myfile
                              this is
                              new contents
                              at top of file
                              NEW_CONTENTS

                              rm "$tmpfile"


                              Notice that the cat command itself is almost the same as your



                              cat myfile <<EOT >>myfile
                              1
                              2
                              3
                              EOT


                              However, cat has to be told to also read its standard input, which it does when one of its filename operands is -. We also can't redirect from the original file and then append the result to the same file, as that creates a loop that would make the file grow until it fills all space on the partition. This is why I first copy the file to a temporary file and then use that to create new contents for the old name.



                              We could also have done



                              tmpfile=$(mktemp)

                              cat - myfile <<NEW_CONTENTS >"$tmpfile" &&
                              this is
                              new contents
                              at top of file
                              NEW_CONTENTS
                              mv "$tmpfile" myfile


                              I.e., write the result to a temporary file and then move that so that it replaces the original. This order of operations is however not guaranteed to preserve ownerships and permissions on myfile.





                              A small shell function that takes standard input and places it atop a given filename:



                              paste_header () {
                              local tmpfile=$(mktemp)

                              trap "rm -f '$tmpfile'" EXIT

                              cat - "$1" >"$tmpfile" &&
                              cat "$tmpfile" >"$1"
                              }


                              The way this is written, it would allow the user to, for example, paste in contents from the clipboard interactively, but would not modify the original file if the input was interrupted by Ctrl+C. The interactive input would need to be terminated by pressing Ctrl+D (which sends EOT, i.e. end-of-text).



                              The function would be used as



                              paste_header filename


                              to interactively paste data to be added into filename (end input with Ctrl+D).



                              or



                              paste_header filename <otherfile


                              to insert data from another file.







                              share|improve this answer














                              share|improve this answer



                              share|improve this answer








                              edited yesterday

























                              answered yesterday









                              KusalanandaKusalananda

                              127k16239393




                              127k16239393























                                  0














                                  Using sed:



                                  $ sed -e 'i1' -e 'i2' test.text
                                  1
                                  2
                                  3





                                  share|improve this answer




























                                    0














                                    Using sed:



                                    $ sed -e 'i1' -e 'i2' test.text
                                    1
                                    2
                                    3





                                    share|improve this answer


























                                      0












                                      0








                                      0







                                      Using sed:



                                      $ sed -e 'i1' -e 'i2' test.text
                                      1
                                      2
                                      3





                                      share|improve this answer













                                      Using sed:



                                      $ sed -e 'i1' -e 'i2' test.text
                                      1
                                      2
                                      3






                                      share|improve this answer












                                      share|improve this answer



                                      share|improve this answer










                                      answered yesterday









                                      OlorinOlorin

                                      3,0691416




                                      3,0691416






























                                          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.




                                          draft saved


                                          draft discarded














                                          StackExchange.ready(
                                          function () {
                                          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f497141%2fhow-to-prepend-multiple-lines-to-a-file%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”?