Search code examples
powershellstreamwriter

How to rearange columns in txt files using powershell


Hello I'm trying to change columns order of a multiple text files in a single directory using powershell and also I need to add a new column with a file name in it. I would like to rewrite each file and not to create a new one.

example: File1.txt original file content:

column1;column2;column3

new file content - File1.txt

column2;column3;column1;File1

. . . FileN.TXT

Here is what I have so far:

Thank you

$reader = [System.IO.File]::OpenText('FILE1.txt')
$writer = New-Object System.IO.StreamWriter 'FILE1-NEW.txt'
for(;;) {
$line = $reader.ReadLine()
if ($null -eq $line) {
    break
}
$data = $line.Split(";")

$BaseName = $_.Basename
$writer.WriteLine('{0},{1},{2},$BaseName', $data[0], $data[2], $data[1])
}
$reader.Close()
$writer.Close()

Solution

  • You're current approach is fine, as long as none of the column values contain the delimiter (;).

    As suggested in the comments, what you can do at the end of each run is just delete the original file, then rename or move the new/temporary to the original file path.

    I'd personally use Path.GetTempFileName() to allocate the temporary file:

    # Gather all the files
    $Files = Get-ChildItem .\path\to\files -Filter *.txt
    
    foreach($txtFile in $Files){
        # Allocate new temp file
        $tempFilepath = [System.IO.Path]::GetTempFileName()
    
        # Open up original file for reading
        $reader = [System.IO.File]::OpenText($txtFile.FullName)
    
        # Open up temp file for writing
        $writer = New-Object System.IO.StreamWriter $tempFilepath
        for(;;) {
            $line = $reader.ReadLine()
            if ($null -eq $line) {
                break
            }
            $data = $line.Split(";")
    
            # Write data in modified order to temp file
            $writer.WriteLine('{0},{1},{2},{3}', $data[0], $data[2], $data[1], $txtFile.Basename)
        }
        $reader.Close()
        $writer.Close()
    
        # Move file into place, -Force will overwrite original
        Move-Item $tempFilepath -Destination $txtFile.FullName -Force
    }