Powershell - Write filename into same file - powershell

I have a lot of .csv Files and I want to write the filename into the same file, at the end of the last position.
For example in C:\CSV I have:
P0_0050569F52981EE39CEF8C857147E850.csv
P0_0050569F52981EE39CEF8D4825092850.csv
P0_0050569F52981EE39CEF8EE13B954850.csv
...and another thousand more of these files
In every one of this files I have some content:
P0_0050569F52981EE39CEF8C857147E850.csv = 365013;253;9001
I want to transform this: 365013;253;9001 to this:
365013;253;9001;
P0_0050569F52981EE39CEF8C857147E850.csv
I cannot find the error...
Get-ChildItem -Filter "*.csv" -Path "C:\CSV" -Recurse | % {
#Open file
$reader = New-Object System.IO.StreamReader $_.FullName
#Ignore first line
$reader.ReadLine() | out-null
#Get name
$filename = $filename
#Write
Add-Content ";" $filename
#Close stream
$reader.Close()
}

MickyB's option should work. Here's another way to do it:
Get-ChildItem -Filter "*.csv" -Path "C:\CSV" -Recurse | foreach {$contents = get-content $_.fullname; $contents +=";"+"`r`n"+$_.name; Set-Content $_.fullname -Value $contents }

This will happen the filename at the end of each CSV.
Get-ChildItem -Filter "*.csv" -Path "C:\CSV" -Recurse | % {
(";"+"`r`n"+$_.name) | Out-File -FilePath $_.fullname -Append
}

Related

How can I get the time and date my PowerShell script deletes a file

I am using the following script to read a list of file names which are then deleted. Is there a way can get an output of the date and time each file is deleted?
$targetFolder = "D:\" $fileList = "C:\DeleteList.txt" Get-ChildItem
-Path "$targetFolder\*" -Recurse -Include #(Get-Content $fileList) | Remove-Item -Verbose
Thanks for any help.
You could keep track of the files that are deleted and the time of deletion by outputting an object with the file's fullname and current date.
This output can then be saved as structured CSV file
$targetFolder = "D:\"
$fileList = Get-Content -Path "C:\DeleteList.txt"
$deleted = Get-ChildItem -Path $targetFolder -Recurse -Include $fileList | ForEach-Object {
# output an object with the current date and the file FullName
$_ | Select-Object #{Name = 'DeletedOn'; Expression = {(Get-Date)}}, FullName
$_ | Remove-Item -WhatIf
}
# output on screen
$deleted | Format-Table -AutoSize
# output to csv file
$deleted | Export-Csv -Path 'C:\RemovedFiles.csv' -NoTypeInformation
Remove the -WhatIf safety-switch if you are satisfied with the results shown on screen.
Would this work?
$targetFolder = "D:"
$fileList = "C:\DeleteList.txt"
$Files = Get-ChildItem -Path "$targetFolder" -Recurse -Include #(Get-Content $fileList)
# Once you have the desires files stored in the $Files variable, then run a Foreach loop.
$Obj = #() # create an array called $Obj
Foreach ($File in $Files)
{
# store info in hash table
$hash = #{
DateTime = (get-date)
fileName = $File.name
fullpath = $File.fullname
}
Write-Host "deleting file $($file.name)" -for cyan
Remove-Item $File.fullname # *** BE VERY CAREFUL!!!***
# record information in an array called $Obj
$Obj += New-Object psobject -Property $hash
}
$Obj | select fileName, DateTime | Export-csv C:\...

Conversion from CSV to TSV with content changes

I need to change CSV File to TSV, and also remove line breaks and double quotes.
Here's the code:
$filePath = "C:\Users\at1704171\Documents\Infinity Scorecard PBIX\converter"
$mkdir = New-Item -ItemType Directory -Force -Path (Join-Path -Path $filePath -ChildPath 'converted')
$files = Get-ChildItem (Join-Path -Path $filePath -ChildPath "*") -Include *.csv
$sep = "`t"
$ext = '.tsv'
foreach($file in $files)
{
$filename = -Join($mkdir,"\",(Get-Item $file).BaseName,$ext)
Import-Csv $file |
ConvertTo-Csv -NoTypeInformation -Delimiter $sep |
% { $_.Replace("`r"," ").Replace("`n"," ").Replace('"',"") } |
Out-File -FilePath $filename -Encoding utf8
}
it's basically converting a CSV File to TSV, but also removing line breaks and double quotes. However I noticed that there are some "tabs" (`t) within the string so I needed to insert another line between "Import" and "Convert" to replace those "tabs" by a space
I do not understand how the syntax works so I literally copied the line below "Convert" since it executes the same function and did this, but it gives an error
$filePath = "C:\Users\at1704171\Documents\Infinity Scorecard PBIX\converter"
$mkdir = New-Item -ItemType Directory -Force -Path (Join-Path -Path $filePath -ChildPath 'converted')
$files = Get-ChildItem (Join-Path -Path $filePath -ChildPath "*") -Include *.csv
$sep = "`t"
$ext = '.tsv'
foreach($file in $files)
{
$filename = -Join($mkdir,"\",(Get-Item $file).BaseName,$ext)
Import-Csv $file |
% { $_.Replace("`t"," ") } | --this is the line I added
ConvertTo-Csv -NoTypeInformation -Delimiter $sep |
% { $_.Replace("`r"," ").Replace("`n"," ").Replace('"',"") } |
Out-File -FilePath $filename -Encoding utf8
}
anybody's help is greatly appreciated here, thank you guys

Count the number of files in the directory as well as the number of folders

Currently , I can export the list to a text file and separate them by share name.
My question is : I want to be able to count the number of files in the directory as well as the number of folders into a separate text file.
I'd like to do in this format for text file , $hostname-$sharename-count.txt
For example:
My desired output:
1000 #Folder count
150 #File count
Here is what I have so far:
$outputDir = 'C:\Output'
$Shares = Get-WmiObject Win32_Share -Filter "not name like '%$'"
$re = ($Shares | ForEach-Object {[Regex]::Escape($_.Path)}) -join '|'
foreach ($Share in $Shares) {
$result = (Get-ChildItem -Path $Share.Path -File -Recurse | Select-Object -Expand FullName) -replace "^($re)\\"
# output the results per share in a text file
$fileOut = Join-Path -Path $outputDir -ChildPath ('{0}-{1}.txt' -f $env:COMPUTERNAME, $Share.Name)
$result | Out-File -FilePath $fileOut -Force
}
You can simply expand the code you have like below:
$outputDir = 'C:\Output'
$Shares = Get-WmiObject Win32_Share -Filter "not name like '%$'"
$re = ($Shares | ForEach-Object {[Regex]::Escape($_.Path)}) -join '|'
foreach ($Share in $Shares) {
$files = (Get-ChildItem -Path $Share.Path -File -Recurse | Select-Object -Expand FullName) -replace "^($re)\\"
# output the list of files per share in a text file
$fileOut = Join-Path -Path $outputDir -ChildPath ('{0}-{1}.txt' -f $env:COMPUTERNAME, $Share.Name)
$files | Out-File -FilePath $fileOut -Force
# output the count results for files and folders per share in a text file
$folders = Get-ChildItem -Path $Share.Path -Directory -Recurse
$content = 'Folders: {0}{1}Files: {2}' -f $folders.Count, [Environment]::NewLine, $files.Count
$fileOut = Join-Path -Path $outputDir -ChildPath ('{0}-{1}-count.txt' -f $env:COMPUTERNAME, $Share.Name)
$content | Out-File -FilePath $fileOut -Force
}
P.S. You can add switch -Force to the Get-ChildItem cmdlet to also get the hidden or system files listed if there are any such files inside the shares
If you just want to have a count, you could do something like this:
$resultForFiles = (Get-ChildItem -Path $Share.Path -File -Recurse | Select-Object -Expand FullName)
$resultForFolders = (Get-ChildItem -Path $Share.Path -Directory -Recurse | Select-Object -Expand FullName)
$resultForFiles.Count | Out-File "Path" -Append
$resultForFolders.Count | Out-File "Path" -Append
The -File switch for Get-ChildItem will only get files and the -Directory will only get folders
You can do this in just one line of code
Get-ChildItem | Measure-Object -Property Mode
The property Mode from Get-ChildItem tells you if you are getting folders, files or others.
You can also use get-help Measure-Object -Examples to check some useful examples on measuring files and folders

Read txt file in folder and fint some text by per sample

I try to read big data log file, in folder C: \ log \ 1 \ i put 2 txt files, i need open-> read all file .txt and find with filter some text like whis: [text]
# Filename: script.ps1
$Files = Get-ChildItem "C:\log\1\" -Filter "*.txt"
foreach ($File in $Files)
{
$StringMatch = $null
$StringMatch = select-string $File -pattern "[Error]"
if ($StringMatch) {out-file -filepath C:\log\outputlog.txt -inputobject $StringMatch}
}
# end of script
not work
Would doing something like a select-string work?
Select-String C:\Scripts\*.txt -pattern "SEARCH STRING HERE" | Format-List
Or if there are multiple files you are wanting to parse maybe use the same select-string but within a loop and output the results.
$Files = Get-ChildItem "C:\log\1\" -Filter "*.txt"
foreach ($File in $Files)
{
$StringMatch = $null
$StringMatch = select-string $File -pattern "SEARCH STRING HERE"
if ($StringMatch) {out-file -filepath c:\outputlog.txt -inputobject $StringMatch}
}
This will print out the file name along with the line number in the file. I hope this is what you are looking for.
Remove-Item -Path C:\log\outlog.txt
$Files = Get-ChildItem "C:\log\1\" -Filter "*.txt"
foreach ($File in $Files)
{
$lineNumber = 0
$content = Get-Content -Path "C:\log\1\$File"
foreach($line in $content)
{
if($line.Contains('[Error]'))
{
Add-Content -Path C:\log\outlog.txt -Value "$File -> $lineNumber"
}
$lineNumber++
}
}
Code below works
It selects strings in txt files in your folder based on -SimpleMatch and then appends it to new.txt file.
Though i do not know how to put two simple matches in one line. Maybe someone does and can post it here
Select-String -Path C:\log\1\*.txt -SimpleMatch "[Error]" -ca | select -exp line | out-file C:\log\1\new.txt -Append
Select-String -Path C:\log\1\*.txt -SimpleMatch "[File]" -ca | select -exp line | out-file C:\log\1\new.txt -Append
Regards
-----edit-----
If you want to you may not append it anywhere just display - simply dont pipe it to out-file
use index then check it :
New-Item C:\log\outputlog.txt
$Files = Get-ChildItem "C:\log\1\" -Include "*.txt"
foreach ($File in $Files)
{
$StringMatch = $null
$StringMatch = Get-Content $File
if($StringMatch.IndexOf("[Error]") -ne -1)
{
Add-Content -Path C:\log\outputlog.txt -Value ($StringMatch+"
-------------------------------------------------------------
")
}
}
# end of script

Read all files, change content, save again

I'm trying to do a replace in content of all files in a certain directory structure.
get-childItem temp\*.* -recurse |
get-content |
foreach-object {$_.replace($stringToFind1, $stringToPlace1)} |
set-content [original filename]
Can I get the filename from the original get-childItem to use it in the set-content?
Add processing for each file:
get-childItem *.* -recurse | % `
{
$filepath = $_.FullName;
(get-content $filepath) |
% { $_ -replace $stringToFind1, $stringToPlace1 } |
set-content $filepath -Force
}
Key points:
$filepath = $_.FullName; — get path to file
(get-content $filepath) — get content and close file
set-content $filepath -Force — save modified content
You can simply use $_, but you need a foreach-object around each file, too. While #akim's answer will work, the use of $filepath is unnecessary:
gci temp\*.* -recurse | foreach-object { (Get-Content $_) | ForEach-Object { $_ -replace $stringToFind1, $stringToPlace1 } | Set-Content $_ }