Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prepend "!" to the beginning of the first line of a file

Tags:

powershell

I have several files that I need to add a "!" to the beginning, just on the first line. I still need to keep the first line's content, just add a "!" as the first character.

Any help would be really appreciated.

Thanks!

Edit: The only thing I could figure out so far was to do the following:

$a = Get-Content 'hh_Regulars3.csv'
$b = '!'
Set-Content 'hh_Regulars3-new.csv' -value $b,$a

This just added the "!" to the top of the file, instead of to the beginning of the first line.

like image 872
thomaskessel Avatar asked Mar 02 '16 19:03

thomaskessel


People also ask

How do you append the first line of a file in Unix?

Use sed 's insert ( i ) option which will insert the text in the preceding line.

How do I add text to the beginning of a file in Bash?

You cannot insert content at the beginning of a file. The only thing you can do is either replace existing content or append bytes after the current end of file.

How do you prepend text in Linux?

It's easy to control whether the new text should be directly prepended to the first line or whether it should be inserted as new line(s) (simply append \n to the printf argument). Unlike the sed solution, it works if the input file is empty ( 0 bytes).


2 Answers

You sent an array to Set-Content with $b,$a. Each array item will be given its own line as you have seen. It would displayed the same way on the prompt if executed.

As long as the file is not too big read it in as one string and add the character in.

$path = 'hh_Regulars3.csv'
"!" + (Get-Content $path -Raw) | Set-Content $path

If you only have PowerShell 2.0 then Out-String would work in place of -Raw

"!" + (Get-Content $path | Out-String) | Set-Content $path

The brackets are important to be sure the file is read in before it goes to through the pipeline. It allows us to both read and write on the same pipeline.

If the file is larger look into using StreamReaders and StreamWriters. This would also have to be used if the trailing new line, created by the Add-Content and Set-Content, is not warranted.

like image 197
Matt Avatar answered Nov 07 '22 06:11

Matt


Late to the party, but thought this might be useful. I needed to perform the operation over a thousand+ large files, and needed something a little more robust and less prone to OOM exceptions. Ended up just writing it leveraging .Net libraries:

function PrependTo-File{
  [cmdletbinding()]
  param(
    [Parameter(
      Position=1,
      ValueFromPipeline=$true,
      Mandatory=$true,
      ValueFromPipelineByPropertyName=$true
    )]
    [System.IO.FileInfo]
    $file,
    [string]
    [Parameter(
      Position=0,
      ValueFromPipeline=$false,
      Mandatory=$true
    )]
    $content
  )

  process{
    if(!$file.exists){
      write-error "$file does not exist";
      return;
    }
    $filepath = $file.fullname;
    $tmptoken = (get-location).path + "\_tmpfile" + $file.name;
    write-verbose "$tmptoken created to as buffer";
    $tfs = [System.io.file]::create($tmptoken);
    $fs = [System.IO.File]::Open($file.fullname,[System.IO.FileMode]::Open,[System.IO.FileAccess]::ReadWrite);
    try{
      $msg = $content.tochararray();
      $tfs.write($msg,0,$msg.length);
      $fs.position = 0;
      $fs.copyTo($tfs);
    }
    catch{
      write-verbose $_.Exception.Message;
    }
    finally{

      $tfs.close();
      # close calls dispose and gc.supressfinalize internally
      $fs.close();
      if($error.count -eq 0){
        write-verbose ("updating $filepath");
        [System.io.File]::Delete($filepath);
        [System.io.file]::Move($tmptoken,$filepath);
      }
      else{
        $error.clear();
        write-verbose ("an error occured, rolling back. $filepath not effected");
        [System.io.file]::Delete($tmptoken);
      }
    }
  }
}

Usage:

PS> get-item fileName.ext | PrependTo-File "contentToAdd`r`n"
like image 33
Kitty Quinn Avatar answered Nov 07 '22 06:11

Kitty Quinn