How to replace the content of every file in the directory? - powershell

There is a function (Function($_)) that replace all "1" with "2" for each file in the directory. New content is written to the file out.txt.
input: in.txt → 111
output: in.txt → 222 → out.txt
Tell me, please, how to make the replacement take place inside of every file?
Get-Content "C:\Dir\*" | ForEach-Object {Function($_)} > C:\Dir\out.txt

Get-Content "C:\Dir\*" will give you the content of everything in C:\Dir in one go, so you won't be able to modify each file individually. You'll also get errors for any directory in C:\Dir.
You need to iterate over each file in the directory and process them individually:
Get-ChildItem 'C:\Dir' -File | ForEach-Object {
$file = $_.FullName
(Get-Content $file) -replace '1','2' | Set-Content $file
}
The parentheses around Get-Content ensure that the file is read and closed again before further processing, otherwise writing to the (still open) file would fail.
Note that the parameter -File is only supported in PowerShell v3 or newer. On older versions you need to replace Get-ChildItem -File with something like this:
Get-ChildItem 'C:\Dir' | Where-Object { -not $_.PSIsContainer } | ...

Related

concatenate columnar output in PowerShell

I want to use PowerShell to generate a list of commands to move files from one location to another. (I'm sure PowersSell could actually do the moving, but I'd like to see the list of commands first ... and yes I know about -WhatIf).
The files are in a series of subfolders one layer down, and need moved to a corresponding series of subfolders on another host. The subfolders have 8-digit identifiers. I need a series of commands like
move c:\certs\40139686\22_05_2018_16_23_Tyre-Calligraphy.jpg \\vcintra2012\images\40139686\Import\22_05_2018_16_23_Tyre-Calligraphy.jpg
move c:\certs\40152609\19_02_2018_11_34_Express.JPG \\vcintra2012\images\40152609\Import\19_02_2018_11_34_Express.JPG
The file needs to go into the \Import subdirectory of the corresponding 8-digit-identifier folder.
The following Powershell will generate the data that I need
dir -Directory |
Select -ExpandProperty Name |
dir -File |
Select-Object -Property Name, #{N='Parent';E={$_.Directory -replace 'C:\\certs\\', ''}}
40139686 22_05_2018_16_23_Tyre-Calligraphy.jpg
40152609 19_02_2018_11_34_Express.JPG
40152609 Express.JPG
40180489 27_11_2018_11_09_Appointment tuesday 5th.jpg
but I am stuck on how to take that data and generate the concatenated string which in PHP would look like this
move c:\certs\$Parent\$Name \\vcintra2012\images\$Parent\Import\$Name
(OK, the backslashes would likely need escaped but hopefully it is clear what I want)
I just don't know to do this sort of concatenation of columnar output - any SO refs I look at e.g.
How do I concatenate strings and variables in PowerShell?
are not about how to do this.
I think I need to pipe the output to an expression that effects the concatenation, perhaps using -join, but I don't know how to refer to $Parent and $Name on the far side of the pipe?
Pipe your output into a ForEach-Object loop where you build the command strings using the format operator (-f):
... | ForEach-Object {
'move c:\certs\{0}\{1} \\vcintra2012\images\{0}\Import\{1}' -f $_.Parent, $_.Name
}
Another approach:
$source = 'C:\certs'
$destination = '\\vcintra2012\images'
Get-ChildItem -Path $source -Depth 1 -Recurse -File | ForEach-Object {
$targetPath = [System.IO.Path]::Combine($destination, $_.Directory.Name , 'Import')
if (!(Test-Path -Path $targetPath -PathType Container)) {
New-Item -Path $targetPath -ItemType Directory | Out-Null
}
$_ | Move-Item -Destination $targetPath
}

Replace letters in list of txt files - powershell

Hi I'm trying to change the letters in various files (which I have in listed in a text file) I can go through the files individually using the command below, but I was wondering if there's a way to loop through the list amending each of the file contents.
example I'd like to change test-pop-test to test-bar-test and this is the content of several files, not the name of the file.
The code I am using is below, amending the names before running.
(Get-Content c:\temp\list.txt) | ForEach-Object { $_ -replace "pop", "bar" } | Set-Content c:\temp\test2.txt
Each object is a text file that I would like it to loop through, so list.txt contains a list of text files where the contents are to be amended, not sure if I explained this very well.. :)
Thanks in advance :)
A basic example:
$Temp = Get-ChildItem C:\Temp -Force
ForEach ($f in $Temp)
{
(Get-Content $f) |
% { $_ -replace 'pop', 'bar' } |
Set-Content $f
}

Powershell Find Replace & Backup

Right now, i am looking to improve my code to use less space and be more intelligent, i need the below code to only backup files IF it's modified by the Find & Replace, right now i'm doing a backup of everything and overwriting old back-ups.
The next thing i would like would be to NOT overwrite the backups, but instead give them a number, so if there are 2 of the same backups in the "backup" folder it would look like this:
Filebackup.DCN3 -> Filebackup1.DCN3
So i always have the original file.
get-childitem -path "C:\Users\Administrator\Desktop\Eurocard\SEB" -filter *.* -recurse | copy-item -destination "C:\Users\Administrator\Desktop\Eurocard\Backup"
(Get-ChildItem "C:\Users\Administrator\Desktop\Eurocard\SEB\*.*" -recurse).FullName |
Foreach-Object {
(Get-Content $_ -Raw).
Replace('*','Æ').
Replace('"','Æ').
Replace('#','Æ').
Replace('¤','Æ').
Replace('&','Æ').
Replace('(','Æ').
Replace(')','Æ').
Replace('=','Æ').
Replace('?','Æ').
Replace('´','Æ').
Replace('`','Æ').
Replace('|','Æ').
Replace('#','Æ').
Replace('£','Æ').
Replace('$','Æ').
Replace('{','Æ').
Replace('[','Æ').
Replace(']','Æ').
Replace('}','Æ').
Replace('^','Æ').
Replace('~','Æ').
Replace('¨','Æ').
Replace('*','Æ').
Replace('<','Æ').
Replace('>','Æ').
Replace('\','Æ').
Replace('_','Æ').
Replace(';','Æ').
Replace('.','Æ').
Replace('!','Æ')|
Set-Content $_
}
Is there anyone who can help with this ?
Well, to start a large portion of your regex replaces probably aren't working, you need to escape most of them...for example "\". Anyways you can shorten up the whole replace to one expression like this:
-replace '[*"#¤&()=?´`|#£${\[\]}^~¨*<>\\_;.!]','Æ'
#query to show it working
'*"#¤&()=?´`|#£${[]}^~¨*<>\_;.!' -replace '[*"#¤&()=?´`|#£${\[\]}^~¨*<>\\_;.!]','Æ'
expanding on that here is how you would get it to only backup if you modify the file:
(Get-ChildItem "C:\Users\Administrator\Desktop\Eurocard\SEB\*.*" -recurse).FullName |
Foreach-Object {
$Content = (Get-Content $_ -Raw)
$Regex = '[*"#¤&()=?´`|#£${\[\]}^~¨*<>\\_;.!]'
If ($Content | Select-String $Regex -Quiet)
{
$Content -Replace $Regex,'Æ'
<#
rest of code block such as copies, backups, renames whatever would go here.
This way it is only taking place if the file has an unwanted character and is
modified
#>
}
}

find and delete lines without string pattern in text files

I'm trying to find out how to use powershell to find and delete lines without certain string pattern in a set of files. For example, I have the following text file:
111111
22x222
333333
44x444
This needs to be turned into:
22x222
44x444
given that the string pattern of 'x' is not in any of the other lines.
How can I issue such a command in powershell to process a bunch of text files?
thanks.
dir | foreach { $out = cat $_ | select-string x; $out | set-content $_ }
The dir command lists the files in the current directory; the foreach goes through each file; cat reads the file and pipes into select-string; select-string finds the lines that contains the specific pattern, which in this case is "x"; the result of select-string is stored in $out; and finally, $out is written to the same file with set-content.
We need the temporary variable $out because you cannot read and write the same file at the same time.
This will process all txt files from the working directory. Each file content is checked and only lines that have 'x' in them are allowed to pass on. The result is written back to the file.
Get-ChildItem *.txt | ForEach-Object{
$content = Get-Content $_.FullName | Where-Object {$_ -match 'x'}
$content | Out-File $_.FullName
}

Powershell script to copy and rename files in a loop

I have a number of files with extension .psa in my Prevalidation folder and I want to:
copy them one by one into my working folder
rename the .psa file to psaload.csv
run a set of commands against the file to load it to my db
and then delete the csv file from my working folder.
This will be repeated for all the .psa files I have on my source folder.
So, the question is how do I execute the set of commands in a loop over as many .psa files as present.
Here's my piece of code testing for only one file in my Prevalidation folder -
Copy-Item C:\Downloads\PreValidation\*.psa C:\Downloads\Validation\WIP
Rename-Item 'C:\Downloads\Validation\WIP\abc 1234.psa' 'psaload1.csv'
Get-Content C:\Downloads\Validation\WIP\psaload1.csv | ForEach-Object { $_.replace("\,"," ") } | Set-Content C:\Downloads\Validation\WIP\psaload.csv
Remove-Item C:\Downloads\Validation\WIP\psaload1.csv
<run the psaload.csv to load to my db>
This is what I intend to do -
Consider multiple .psa files in my C:\Downloads\Prevalidation folder.
For each C:\Downloads\PreValidation\*.psa
BEGIN LOOP
Copy-Item C:\Downloads\PreValidation\aaaa.psa C:\Downloads\Validation\WIP\aaaa.psa
Rename-Item 'C:\Downloads\Validation\WIP\aaaa.psa' 'psaload1.csv'
Get-Content C:\Downloads\Validation\WIP\psaload1.csv | ForEach-Object { $_.replace("\,"," ") } | Set-Content C:\Downloads\Validation\WIP\psaload.csv
Remove-Item C:\Downloads\Validation\WIP\psaload1.csv
END LOOP
I am looking for the syntax to run these set of commands for each files one by one as present in my /prevalidation folder.
Since all the other answers were quite horrible code and not very idiomatic PowerShell, here is my take (though untested):
# Get all .psa files
Get-ChildItem C:\Downloads\PreValidation\*.psa |
ForEach-Object {
# Load the file's contents, replace commas with spaces
(Get-Content $_) -replace ',', ' ' |
# and write it to the correct folder and file name
Out-File C:\Downloads\WIP\psaload.csv
# I guess you'd run whatever you're doing against the file here,
# not after the loop
Remove-Item C:\Downloads\WIP\psaload.csv
}
You can use foreach with Get-Item to do the loop. Get-Item will return a FileInfo
object that you can use to get the file name (and other info) from. So you could do something like:
foreach($file in (Get-Item .\*.psa))
{
Copy-Item $file.FullName "C:\Downloads\Validation\WIP\$($file.Name)";
}
etc.
Try this:
$a = Get-Item .\*.psa
foreach($file in $a)
{
Copy-Item $file.FullName "C:\Downloads\Validation\WIP\$($file.Name.replace(".psa",".psload.csv)";
remove-item $file
}