How to put and remove comment on line 20 using powershell? [duplicate] - powershell

I want to add text into specific line of txt file. I can't find any solution on internet.
This code adds text in further line (I want for example second line):
$test_out = "test"
$test_out | Add-Content "C:\tmp\test.txt"

If you want to add text to the end of a specific line, you can do it like this
$fileContent = Get-Content $filePath
$fileContent[$lineNumber-1] += $textToAdd
$fileContent | Set-Content $filePath
If you want to replace the text instead of adding, just remove the '+' sign.
You do of course have to set the variables
$filePath, $textToAdd and $lineNumber first.

Here a solution which reads the content of the file and access the line using the array index (-1). This example adds the line test and a line break to the second line.
$filePath = 'C:\tmp\test.txt'
$test_out = "test"
$fileContent = Get-Content -Path $filePath
$fileContent[1] = "{0}`r`n{1}" -f $test_out, $fileContent[1]
$fileContent | Set-Content $filePath

Related

Trouble reading last line of CSV

I am getting CSV files (with no header) from another system. The last line ends the file, (there is not a newline after the last line of data). When I try Import-CSV, it will not read the last line of the file.
I do not have the ability to have the input file changed to include the newline.
I have noticed that the Get-Content doesn't have a problem reading the entire file, but then it isn't a CSV and I'm unable to reference the fields in the file.
Currently I'm doing:
$w = Import-CSV -path c:\temp\input.txt -header 'head1', 'head2', 'head3'
This will not read the last line of the file
This reads the entire file:
$w = Get-Content -path c:\temp\input.txt
But the data doesn't have the ability to reference the fields like: $w.head1
Is there a way to get Import-CSV to read the file including the last line?
OR Is there a way to read in the data using Get-Content, adding a header to it and then converting it back to a CSV?
I've tried use ConvertTo-CSV but have not had success:
$w = Get-Content -path c:\temp\input.txt
$csvdata = $w | ConvertTo-CSV # No header option for this function
I'd rather not create an intermediate file unless absolutely necessary.
You're very close! What you're after is not ConvertTo-Csv, you already have the file contents in CSV-format after all. So change that to ConvertFrom-Csv instead, which incidentally does support the -Headers parameter. So something like this:
$w = Get-Content -path c:\temp\input.txt
$csvdata = $w | ConvertFrom-Csv -Header 'head1', 'head2', 'head3'
If I understand correctly, you know the number of columns in the file and all it is missing is a header line. Since in your code you do not specify a -Delimiter parameter I'm assuming the delimiter character used in the file is a comma.
Best thing to do IMHO is to create a new output file and always keep the original.
$fileIn = 'c:\temp\input.txt'
$fileOut = 'c:\temp\input.csv'
# write the header line to a new file
Set-Content -Path $fileOut -Value 'head1,head2,head3'
# read the original file and append it to the one you have just created
Get-Content -Path $fileIn -Raw | Add-Content -Path $fileOut
If your file is really large, below a faster alternative:
$fileIn = 'c:\temp\input.txt'
$fileOut = 'c:\temp\input.csv'
# write the header line to a new file
Set-Content -Path $fileOut -Value 'head1,head2,head3'
# read the original file and append it to the one you have just created
[System.IO.File]::AppendAllText($fileOut, ([System.IO.File]::ReadAllText($fileIn)))
If you really do want to take the risk and overwrite the original file, you can do this:
$file = 'c:\temp\input.txt'
$content = Get-Content -Path $fileIn -Raw
# write the header line to a the file destroying what was in there
Set-Content -Path $file -Value 'head1,head2,head3'
# append the original content to it
$content | Add-Content -Path $file

Change value on specific lines of multiple files

I am testing software which has settings in text files.
Now i need to change a specific line in ~100 files.
I searched hours for it and i am close to a solution. But dont know how to get it done.
A solution in notepad++ would be nice, but i tried it with powershell with the following command:
# File to change
$file = *.dat
# Get file content and store it into $content variable
$content = Get-Content -Path $file
# Replace the line number 40 with "0"
$content[39] = '"0"'
# Set the new content
$content | Set-Content -Path $file
It changes the specific line, but it also adds the data of all the files, in all the files in the folder. So in case of 200 lines the files now have 20000 lines. Every file.
I want to change in all the files linenumber 40:
"0"
change to
"1"
Because there are multiple values with "0" on other lines, i only want to change line 40 in multiple files.
You probably have to iterate over these files. Example:
Get-ChildItem *.dat | ForEach-Object {
$content = Get-Content -Path $_
$content[39] = '"0"'
$content | Set-Content -Path $_
}

New line is being added after find and replace [duplicate]

This question already has answers here:
How can I prevent additional newlines with set-content while keeping existing ones when saving in UTF8?
(2 answers)
Set-Content appends a newline (line break, CRLF) at the end of my file
(3 answers)
Closed 4 years ago.
I have a snippet of code which gets the content of each file and will replace values within it if it matches my variable list.
The code works fine. However, after the scan it's leaving a blank line at the end of the file which I do not want to happen.
# From the location set in the first statement
# Recurse through each file in each folder that has an extension defined
# in-Include
$configFiles = Get-ChildItem $Destination -Recurse -File -Exclude *.exe,*.css,*.scss,*.png,*.min.js
foreach ($file in $configFiles) {
Write-Host $file.FullName
# Get the content of each file and search and replace values as defined in
# the searc/replace table
$fileContent = Get-Content $file.FullName
$fileContent | ForEach-Object {
$line = $_
$lookupTable.GetEnumerator() | ForEach-Object {
# [Regex]::Escape($_.Key) treats regex metacharacters in the search
# string as string literals
if ($line -match [Regex]::Escape($_.Key)) {
$line = $line -replace [Regex]::Escape($_.Key), $_.Value
}
}
$line
} | Set-Content $file.FullName
}
I've tried adding:
Set-Content $file.FullName -NoNewline
This just puts everything in the file on one line.
Some files will already have a blank line at the end which I want to stay the same, so I can't just remove the last line of every file.
How do I stop this script from adding a new line once finished scanning?
$lookuptable for reference:
$lookupTable = #{
'Dummy' = $ReplacementValue
'Dummy2' = $ReplacementValue
}

How to read a file line by line and create another new file with that content using powershell

I have a file 'abc.txt' that contains below lines.
c:myfilepath\filepath\filepath1\file1.csv
c:myfilepath\filepath\filepath1\file2.csv
c:myfilepath\filepath\filepath1\file2.csv
How to loop through the above file 'abc.txt' and read line by line and create another file called 'xyz.txt' that should contains like below. The file name in the path in 'xyz.txt' should be different, see below (ex. newfile_file1.txt)
c:mynewfile\newfilepath\newfilepath1\newfile_file1.txt (<-This is
corresponding to file1.csv)
c:mynewfile\newfilepath\newfilepath1\newfile_file2.txt
c:mynewfile\newfilepath\newfilepath1\newfile_file2.txt
I've tried using Get-Content to loop through the file but I just get nothing returned. I'm unclear as to where to put the syntax and how to completely construct it.
This should do it (edited to get file names and paths as requested, and dynamic so the paths in the abc-file are used).
$f = Get-Content C:\temp\abc.txt # this is the contents-file
foreach ($r in $f)
{
$r2 = (Split-Path $r).Replace("\", "\new") + '\newfile_' + [io.path]::GetFileNameWithoutExtension($r) + '.txt'
$r2 = $r2.replace(":\", ":\mynewfile\")
Get-Content $r | Out-File -filepath $r2
}
Assuming all of your file paths start with c:myfilepath\filepath\filepath1, then you can just replace the string then Out-File it.
$File1 = get-content E:\abc.txt
$File1 -replace ('c:myfilepath\\filepath\\filepath1\\', 'c:mynewfile\newfilepath\newfilepath1\newfile_') |
Out-File E:\xyz.txt
Note the double backslashes \\ which escape the regex.

Find group of words in a text file and extract the line to new text file

txt contains word "hi" "hello" "aloha" as per below
hi
hello
aloha
And I have one more file abc.txt which contains many words including the above 3 words. Now I developed a PowerShell script to search the words in abc.txt and extract the line containing the words to a new file done.txt. I use
-match command to find the word.
How to use the file ref.txt which contains the words for the finding, instead of declare the words in coding?
I would like to develop it in cmd.exe instead of PowerShell.
$source = "C:\temp\abc.txt"
$destination = "C:\temp\done.txt"
$hits = select-string -Path $source -SimpleMatch "hi","hello","aloha"
$filecontents = get-content $source
foreach($hit in $hits)
{
$filecontents[$hit.linenumber-1]| out-file -append $destination
"" |out-file -append $destination
}
This should do the batch trick:
findstr /G:ref.txt abc.txt >> done.txt
This would print all lines containing the stings in ref.txt in abc.txt to done.txt
Have I understood you question correctly?
To cover the PowerShell aspect of this question...
To get the patterns you want from file is rather easy since Select-String supports strings arrays for the -Pattern parameter. In its simplest form you could just do something like this
$patterns = Get-Content c:\temp\ref.txt | Where-Object{$_}
$hits = Select-String c:\temp\test.txt -Pattern $patterns -SimpleMatch
Your file contained a blank which I was not sure was on purpose or not. I used Where-Object{$_} to filter that out just in case. Then just pass that string array $patterns to the parameter -Pattern.
The rest of your code after that could use a little tune up. There is no need to read the source file in a second time just to output the matches again. Your output is just the matching line with a newline following.
$patterns = Get-Content c:\temp\ref.txt | Where-Object{$_}
$results = Select-String c:\temp\test.txt -Pattern $patterns -SimpleMatch
$results.Line | ForEach-Object{"$_`r`n"} | Set-Content C:\temp\out.txt
Probably not the best way to get the desired output but it should work regardless.