I am creating a script to get the file version of the dlls and export the output to a csv file , but I want to give particular headers to csv file. How should I do it ? I also need to add a new system date and time column to the csv file.
$j = 'C:\Program Files (x86)\anyfilepatha\'
$files = get-childitem $j -recurse -Include *.dll
$cvsdataFile = 'C:\Program Files\MySQL\Connector ODBC 8.0\dllsinfo.csv'
# Add-Content -Path "C:\Program Files\MySQL\Connector ODBC 8.0\dllsinfo.csv" -Value "Dlls" , "Version Name" , "Location"
$header = foreach ($i in $files)
{
if($i.Name -like '*Eclipsys*' -or $i.Name -like '*Helios*')
{
continue;
}
$verison = [System.Diagnostics.FileVersionInfo]::GetVersionInfo($i).FileVersion
if($verison -eq $null)
{
$i.FullName | Out-File NoVersion.txt -append
}
else
{
Write-Host $i ----> $verison
"{0}`t{1}`t{2} " -f $i, [System.Diagnostics.FileVersionInfo]:: GetVersionInfo($i).FileVersion, $i.CreationTime, $i.FullName | Out-File -Append $cvsdataFile
}
}
You could do it with a one liner. You can exclude items with -Exclude parameter and PowerShell calculated properties for adding new columns. See more about calculated properties here.
Get-ChildItem -Path $j -File -Exclude '*Eclipsys*','*Helios*' -Include *.dll |
Select-Object -Property #{E={$_.versioninfo.Fileversion};l='Version'},#{E={Get-Date -f 'dd/mm/yyyy'};l='Date'},#{E={Get-Date -f 'hh:mm:ss ttt='};L='Time'}
Related
With this code I get the data but is not reflected on the txt file. I just get a bunch of Microsoft.PowerShell.Commands.Internal.Format.FormatStartData.
Microsoft.PowerShell.Commands.Internal.Format.GroupStartData
Microsoft.PowerShell.Commands.Internal.Format.FormatEntryData
Instead the names of each file.
Here is the code:
param(
[string]$foldername = 'unknown'
)
if (Test-Path $foldername){
$location = Join-Path -Path $HOME -ChildPath "files.txt"
$files = Get-ChildItem $foldername | Where-Object {$_.PsIsContainer -ne $True} | Format-Table
Name
$amount = Get-ChildItem $foldername | Where-Object {$_.PsIsContainer -ne $True} | Measure-
Object
Add-Content -Path $location -Value $files
Write-Host $amount.count "filenames were written to file" $location
}
else {Write-Host "Sorry,", $foldername, "does not exist."
break
}
First get-childitem supports the switch File, no need to pipe and filter. The Format-Table is used to format the output displayed on the screen, so as you want to write to a file you do not need it.
Also only use break within a loop, if you want to stop the processing use return instead.
param(
[string]$foldername = 'unknown'
)
if (Test-Path $foldername){
$location = Join-Path -Path $HOME -ChildPath "files.txt"
#gets all files in the specified path
$files = Get-ChildItem $foldername -File
#counts the number of files
$amount = $files.count
#If you want the fullpath in the logfile use $files.fullname if you only want the name use $files.name
$files.FullName | Add-Content -Path $location
Write-Host "$amount filenames were written to file $location"
}
else {
Write-Host "Sorry, $foldername, does not exist."
return
}
In a directory, there are files with the following filenames:
ExampleFile.mp3
ExampleFile_pn.mp3
ExampleFile2.mp3
ExampleFile2_pn.mp3
ExampleFile3.mp3
I want to iterate through the directory, and IF there is a filename that contains the string '_pn.mp3', I want to test if there is a similarly named file without the '_pn.mp3' in the same directory. If that file exists, I want to remove it.
In the above example, I'd want to remove:
ExampleFile.mp3
ExampleFile2.mp3
and I'd want to keep ExampleFile3.mp3
Here's what I have so far:
$pattern = "_pn.mp3"
$files = Get-ChildItem -Path '$path' | Where-Object {! $_.PSIsContainer}
Foreach ($file in $files) {
If($file.Name -match $pattern){
# filename with _pn.mp3 exists
Write-Host $file.Name
# search in the current directory for the same filename without _pn
<# If(Test-Path $currentdir $filename without _pn.mp3) {
Remove-Item -Force}
#>
}
enter code here
You could use Group-Object to group all files by their BaseName (with the pattern removed), and then loop over the groups where there are more than one file. The result of grouping the files and filtering by count would look like this:
$files | Group-Object { $_.BaseName.Replace($pattern,'') } |
Where-Object Count -GT 1
Count Name Group
----- ---- -----
2 ExampleFile {ExampleFile.mp3, ExampleFile_pn.mp3}
2 ExampleFile2 {ExampleFile2.mp3, ExampleFile2_pn.mp3}
Then if we loop over these groups we can search for the files that do not end with the $pattern:
#'
ExampleFile.mp3
ExampleFile_pn.mp3
ExampleFile2.mp3
ExampleFile2_pn.mp3
ExampleFile3.mp3
'# -split '\r?\n' -as [System.IO.FileInfo[]] | Set-Variable files
$pattern = "_pn"
$files | Group-Object { $_.BaseName.Replace($pattern,'') } |
Where-Object Count -GT 1 | ForEach-Object {
$_.Group.Where({-not $_.BaseName.Endswith($pattern)})
}
This is how your code would look like, remove the -WhatIf switch if you consider the code is doing what you wanted.
$pattern = "_pn.mp3"
$files = Get-ChildItem -Path -Filter *.mp3 -File
$files | Group-Object { $_.BaseName.Replace($pattern,'') } |
Where-Object Count -GT 1 | ForEach-Object {
$toRemove = $_.Group.Where({-not $_.BaseName.Endswith($pattern)})
Remove-Item $toRemove -WhatIf
}
I think you can get by here by adding file names into a hash map as you go. If you encounter a file with the ending you are interested in, check if a similar file name was added. If so, remove both the file and the similar match.
$ending = "_pn.mp3"
$files = Get-ChildItem -Path $path -File | Where-Object { ! $_.PSIsContainer }
$hash = #{}
Foreach ($file in $files) {
# Check if file has an ending we are interested in
If ($file.Name.EndsWith($ending)) {
$similar = $file.Name.Split($ending)[0] + ".mp3"
# Check if we have seen the similar file in the hashmap
If ($hash.Contains($similar)) {
Write-Host $file.Name
Write-Host $similar
Remove-Item -Force $file
Remove-Item -Force $hash[$similar]
# Remove similar from hashmap as it is removed and no longer of interest
$hash.Remove($similar)
}
}
else {
# Add entry for file name and reference to the file
$hash.Add($file.Name, $file)
}
}
Just get a list of the files with the _pn then process against the rest.
$pattern = "*_pn.mp3"
$files = Get-ChildItem -Path "$path" -File -filter "$pattern"
Foreach ($file in $files) {
$TestFN = $file.name -replace("_pn","")
If (Test-Path -Path $(Join-Path -Path $Path -ChildPath $TestFN)) {
$file | Remove-Item -force
}
} #End Foreach
My goal is to create a PS script that does the following:
a) scans a source directory and produces a list of files that have a matching pattern that I pass in found inside the files
b) take the list of those files and Copy-Item to move and then archive it.
I have this process working for when I "-Filter" on a filename, but can't seem to get my script to work when using "Select-String -pattern". When it gets to the "$FileNames = #($Files | %{$_.Path.Substring($Source.Length)})" part of the code, it says file does not exist as its passing in the #{Path} code?
View of error
If ({$PatternIdentifier -ne "" -and $FileIdentifier -eq "" -and $FileExtension -ne ""})
{
$Files = get-childitem $Source -Filter $FileExtension | Select-String -pattern $PatternIdentifier -SimpleMatch |Select Path
}
$FileNames = #($Files | %{$_.Path.Substring($Source.Length)})
if($Files.Count -ne 0)
{
if ((test-path $ArchiveDestination) -eq 0)
{
New-Item -ItemType Directory -Force -Path $ArchiveDestination
}
foreach ($File in $Files)
{
Copy-Item $File -Destination $DestinationFolder
Copy-Item $File -Destination $ArchiveDestination
$count++
}
if($error.length -lt 0)
{
Write-Host ("Copied {0} files!!" -f $count)
$answer = $FilesTotalCount -$count
}
}
Get the value from the property:
|Select -expand path
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
I wrote a powershell script which will iterate through three different path and get list of files that are less then 7 years and delete them from current timestamp.
I am getting creation year of file and if am able to recursively iterate through all those three path.
Problem is out of 3, two paths have too many folders and files due to which when script is in loop it shows memory exception. Also I will not be able to set maxmemorypershellMB, since I don't have access.
Anything else that I can do this to avoid memory exception
this is piece of code below:
$files = Get-ChildItem "$path" –Recurse -file
for ($i=0; $i -lt $files.Count; $i++) {
$outfile = $files[$i].FullName #file name
$FileDate = (Get-ChildItem $outfile).CreationTime #get creation date of file
$creationYear = $FileDate.Year
$creationMonth =$FileDate.Month #get only year out of creation date
If( $creationYear -lt $purgeYear ){
If (Test-Path $outfile){ #check if file exist then only proceed
$text=[string]$creationYear+" "+$outfile
$text >> 'listOfFilesToBeDeleted_PROD.txt' #this will get list of files to be deleted
#remove-item $outfile
}
}
}
You could try to filter the the files using where-object instead of a for loop:
$limit = (Get-Date).AddYears(-7)
$path = "c:\"
$outfile = "c:\test.txt"
Get-ChildItem -Path "$path" -Recurse -file |
Where-Object { $_.CreationTime -lt $limit } |
foreach { '{0} {1}' -f $_.CreationTime, $_.FullName |
Out-File -FilePath $outfile -Append }
Solution for your comment:
# retrieve all affected files and select the fullname and the creationtime
$affectedFiles = Get-ChildItem -Path "$path" -Recurse -file |
Where-Object { $_.CreationTime.Year -lt $purgeYear } |
select FullName, CreationTime
foreach ($file in $affectedFiles)
{
# write the file to listOfFilesToBeDeleted
'{0} {1}' -f $file.CreationTime.Year, $file.FullName |
Out-File -FilePath listOfFilesToBeDeleted.txt -Append
# delete the file
Remove-Item -Path $file.FullName -Force
}