Delete Files Older Than X Days: Presentation of Data/Logging Files - powershell

I'm new to Powershell, I'm creating a code to delete a file/s if more than "x" days.
I'm almost done. Need your help in representing my date (table) and should not produce a log file if no files will be delete.
Here's my code:
$max_days = "-30"
$curr_date = Get-Date
$del_date = $curr_date.AddDays($max_days)
$Path = "C:\Desktop\Code"
$DateTime = Get-Date -Format "D=yyyy-MM-dd_T=HH-mm-ss"
$itemsearch = Get-ChildItem C:\Test -Recurse | Where-Object { $_.LastWriteTime -lt $del_date}
Foreach ($item in $itemsearch)
{
Write "File:", $item.Name "Modified:", $item.LastWriteTime "Path:", $item.FullName "Date Deleted:" $del_date | Out-File "C:\Desktop\Code\Deleted\SFTP_DeleteFiles_WORKSPACE_$DateTime.txt" -append
$item | Remove-Item
}
Can anyone please help me? It's already working by the way.
Just need to present the data in table form and don't create a log file if there's nothing to delete.
Update:
Already solved the condition statement by doing:
if($itemsearch)
{
Foreach ($item in $itemsearch)
{
Write "File:", $item.Name "Modified:", $item.LastWriteTime "Path:", $item.FullName "Date Deleted:" $del_date | Out-File "C:\Desktop\Code\Deleted\SFTP_DeleteFiles_WORKSPACE_$DateTime.txt" -append
$item | Remove-Item
}
}
else
{
Write "No files will be deleted."
}
Thanks!
What I want to display it in Excel/Text file is like this one:
http://i59.tinypic.com/30wv33d.jpg
Anyone?
It returns me with this one:
IsReadOnly;"IsFixedSize";"IsSynchronized";"Keys";"Values";"SyncRoot";"Count"
False;"False";"False";"System.Collections.Hashtable+KeyCollection";"System.Collections.Hashtable+ValueCollection";"System.Object";"4"
False;"False";"False";"System.Collections.Hashtable+KeyCollection";"System.Collections.Hashtable+ValueCollection";"System.Object";"4"
False;"False";"False";"System.Collections.Hashtable+KeyCollection";"System.Collections.Hashtable+ValueCollection";"System.Object";"4"
False;"False";"False";"System.Collections.Hashtable+KeyCollection";"System.Collections.Hashtable+ValueCollection";"System.Object";"4"
In Excel. Do you have any idea? I have to search it though.

To introduce tabular logging I would use a CSV file as output by replacing your foreach block by this code:
$results = #()
foreach ($item in $itemsearch)
{
$success = $true
try
{
$item | Remove-Item
}
catch
{
$success = $false
}
if( $success -eq $true )
{
Write-Host $item.FullName 'successfully deleted.'
$results += [PSCustomObject]#{'File'=$item.Name;'Modified'=$item.LastWriteTime;'Path'=$item.FullName;'Date Deleted'=$del_date;'State'='SUCCESS'}
}
else
{
Write-Host 'Error deleting' $item.FullName
$results += [PSCustomObject]#{'File'=$item.Name;'Modified'=$item.LastWriteTime;'Path'=$item.FullName;'Date Deleted'=$del_date;'State'='ERROR'}
}
}
$results | Export-Csv -Path "C:\Desktop\Code\Deleted\SFTP_DeleteFiles_WORKSPACE_$DateTime.csv" -Encoding UTF8 -Delimiter ';' -NoTypeInformation
First an empty array is created ($results).
The try/catch block is here to detect if the deletion succeeded or not, then the appropriate line is added to $results.
At the end the $results array is exported to CSV with ';' separator so you can open it right away with Excel.

Related

How can I filter by day and month in a txt file with powershell

I use logging in my script and write this with day, month and time:
$LogTime = Get-Date -Format "dd-MM HH:mm"
I want to remove all lines older than a month from the file
I wanted to do it like this but it doesn't work:
$DateOld = (get-date (get-date).addDays(-30) -UFormat "%d-%m")
$RemoveLog = get-content -Path C:\.....\Log\UserLog.txt | where {($_.split('-'))[1] -gt $DateOld} | Set-Content "C:\......\Log\out.txt" | Out-Null
Remove-Item -Path C:\........\Log\UserLog.txt -Force | Out-Null
Rename-Item -Path "C:\.........\Log\out.txt" -NewName "UserLog.txt" | Out-Null
The line in the log looks like this:
20-09 11:30 ::: Line with info about log
You may use [datetime]::ParseExact() method to read your file dates and times as [datetime] objects. You may use Move-Item to overwrite a file with a new name using its -Force parameter.
$DateOld = (Get-Date).AddDays(-30)
Get-Content UserLog.txt | Where {
[datetime]::ParseExact([string](-split $_)[0..1],'dd-MM HH:mm',
[System.Globalization.DateTimeFormatInfo]::InvariantInfo) -ge $DateOld
} | Set-Content out.txt
Move-Item out.txt UserLog.txt -Force
Using -split value, value splits based on a single space delimiter. Since we only want the first two elements, we use range 0..1 for the first two resulting elements. Casting to [string] rejoins the split items with a space delimiter.
Something like this.
Remarks:
-the powershell array gets slow on big arrays, you will then better use an generic.list
its just a first draft, depending on the exact requirements and logfile you will need some fine-tuning and / or exception handling, but you should get the idea:
#tmp 20 09 2021
$logfile = 'your path'
[array]$log = Get-Content $logfile
$newLog = #()
$limitDate = (Get-Date).AddDays(-30)
foreach ($line in $log) {
$regex = [regex]::match($line, '(\d{2}-\d{2})\s\d{2}:\d{2}')
if($regex.Success -eq 'True') {
$lineDate = [datetime]::ParseExact($regex.Groups[1].Value.ToString(), "dd-MM", $null)
if ($lineDate -ge $limitDate) {
$newLog += $line
}
}
else {
[console]::WriteLine('Big Exception in Logfile! Will Quit')
exit
}
}
Remove-Item $logfile -Force
if(-not (Test-Path $logfile)) {
$newLog | Out-File $logfile
}
else {
[console]::WriteLine('Big Exception in Logfile! Please Investigate')
}

How to check duplicate multiple file using powershell?

I want to check duplicate file.If the condition of the file like this, it means duplicate. The same name but different extension.
AAA18WWQ6BT602.PRO
AAA18WWQ6BT602.XML
I can figure out this case with my script. But I have problem if I have this more than 1 .XML file like this
AAA18WWQ6BT602.PRO
AAA18WWQ6BT602.XML
AAA18WWQ6BT601.XML
AAA18WWQ6BT604.XML
This case, it will not detect that file AAA18WWQ6BT602.PRO and AAA18WWQ6BT602.XML duplicated.
Anyone can help me please.
Thanks
$duplicate = #()
#(Get-ChildItem "$Flag_Path\*.xml") | ForEach-Object { $duplicate += $_.basename }
if(Test-Path -Path "$Flag_Path\*$duplicate*" -Exclude *.xml)
{
Get-ChildItem -Path "$Flag_Path\*$duplicate*" -Include *.xml | Out-File $Flag_Path\Flag_Duplicate
Write-Host "Flag duplicated, continue for Error_Monitoring"
pause
Error_Monitoring
}
else{
Write-Host "Flag does not duplicate, continue the process"
}
The -Include parameter only works if the path on Get-ChildItem ends in \* OR if the -Recurse switch is used.
The following should do what you want:
$flagFolder = 'D:\*'
$dupeReport = 'D:\Flag_Duplicate.txt'
$duplicates = Get-ChildItem -Path $flagFolder -File -Include '*.xml', '*.pro' |
Group-Object -Property BaseName | Where-Object { $_.Count -gt 1 }
if ($duplicates) {
# output the duplicate XML to Flag_Duplicate.txt
$duplicates.Group | Where-Object {$_.Extension -eq '.xml' } | ForEach-Object {
$_.FullName | Out-File -FilePath $dupeReport -Append
}
# do the rest of your code
Write-Host "Flag duplicated, continue for Error_Monitoring"
Error_Monitoring
}
else {
Write-Host "Flag does not duplicate, continue the process"
}
Your script does not iterate correctly. You need to have an iteration to check. The Test-Path logic looks mixed up to me. I tried to keep as much of your code as possible.
This script checks for a any xml basename filename against any suffix duplicate (not only pro):
$Flag_Path = "C:\dir_to_be_checked"
$xmlFilesArray = #()
$allFilesExceptXml = #() # all files excluding xml files
# Get all the xml files
Get-ChildItem -Path $Flag_Path -Include "*.xml" | ForEach-Object { $xmlFilesArray += $_.basename }
# Get all files from the directory the xml files
Get-ChildItem -Path $Flag_Path -Exclude "*.xml" | ForEach-Object { $allFilesExceptXml += $_.basename }
# Iterate over list of files names without suffix
ForEach ($xmlFile in $xmlFilesArray) {
ForEach ($fileToCheck in $allFilesExceptXml) {
If ($xmlFile -eq $fileToCheck) {
# logging the duplicate file (specifying utf8 or the output would be UTF-16)
Write-Output "$Flag_Path\$xmlFile.xml" | Out-File -Append -Encoding utf8 $Flag_Path\Flag_Duplicate
Write-Host "Flag duplicated, continue with duplicate search"
# pause
Write-Host "Press any key to continue ..."
$x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
Error_Monitoring
} Else {
Write-Host "Flag is not duplicated. Continue with the search."
}
}
}

Issues with Copy-item script

I have a script that needs to copy a list of files to ceraitn directories and locations on target servers.
I was able to understand that I need to creat an csv file as follows:
I need to understand from you how to make the files from source location to their adjacent file in target location. Any ideas?
My code looks like this:
# customize log file
$date = (Get-Date -Format d).ToString() | foreach {$_ -replace "/", "_"}
$time = (Get-Date)
$scriptDir = "D:\Scripts\ServerBuildToolkitT1\SingleFileUpfate\"
$logDir = "D:\Scripts\ServerBuildToolkitT1\Logs\SingleFileUpfate\"
$logFileName = "SingleFileUpfate $date.log"
$sources = #()
$destinsyions = #()
function CSV {
Import-Csv D:\Scripts_PS\SD.csv | ForEach-Object {
$sources += $_."Source Location"
$destinations += $_."Destination Location"
}
}
# this file contains the list of destination server that you want copy
# file/folder to
$computers = Get-Content "D:\Scripts_PS\ServerList.txt"
function main
{
foreach ($computer in $computers) {
foreach ($destination in $destinations) {
Write-Output "$([DateTime]::Now) Copying files update to $computer now" |
Out-File -FilePath "$logDir\$logFileName" -Append
Copy-Item $sources -Destination "\\$computer\$destination" -Force -Recurse -Verbose:$false
}
}
}
csv
main
Write-Output "$([DateTime]::Now) the operation SingleFileUpdate completed successefully" |
Out-File -FilePath "$logDir\$logFileName" -Append
i have updtaed the Script (as seen above) and now i am getting the following ERROR
"WARNING: One or more headers were not specified. Default names starting with "H" have been used in place of any missing headers."

Powershell check whether a file exists

On Windows 7 x64, Powershell 3.0:
I have a directory where I download files to, this is done with a .csv file.
A sample of the files is:
008KS04.zip
008KS05.zip
008KS06.zip
008KS07.zip
008KS08.zip
008KS09.zip
I have a Csv, op wich this is a sample:
Documentnummer,Versie,Status,Geocode,IDS datum,Documentgroep (Omsch),Documenttype (Wrd),Tekeningnummer
550164,I,AB,008,26.03.2016,Themalagen OI,KS,008KS09.zip
550163,D,AB,008,19.07.2013,Themalagen OI,KS,008KS08.zip
550162,D,AB,008,19.07.2013,Themalagen OI,KS,008KS07.zip
550161,C,AB,008,19.07.2013,Themalagen OI,KS,008KS06.zip
550160,D,AB,008,19.07.2013,Themalagen OI,KS,008KS05.zip
550159,E,AB,008,15.08.2014,Themalagen OI,KS,008KS04.zip
So, lets say the files are in c:\test\
and the csv in C:\drawings.csv
I want the files that are missing in a csv, lets say C:\missing.csv
At first I tried with one drawing in a variable:
$drawnr = '008KS09.zip'
$destcsv = "C:\missing.csv"
Set-Location C:\test
If(Test-Path -Path ${drawnr}) {
Write-Output "${drawnr}'.zip' exists"
} Else {
Write-Output "${drawnr}'.zip' doesnt exist"
${drawnr} | Export-Csv $destcsv -Append -NoTypeInformation
}
The output when having an existing and a non existsing drawing in the variable
This works perfect, see image but using the CSV as input, I can't get it to work.
This is what I have so far:
$sourcecsv = 'C:\drawings.csv'
$destcsv = 'C:\missing.csv'
Set-Location 'C:\test\'
Import-Csv $sourcecsv | Select-object -Property Tekeningnummer | ForEach {
Write-Output "${_} is the current object" #For Testing purpuse
If (Test-Path -Path ${_}) {
Write-Output "${_} does exist"
} Else {
Write-Output "${_} doesnt exist"
${_} | Export-Csv $destcsv -Append -NoTypeInformation
}
}
This tells me that none of the files exist, while all do exist.
See the picture to see the output of PowerShell and the content written to the missing.csv
The picture of the output where all files are reported as non existend
I'm not sure I get your intent, but it looks like this might work.
$sourcecsv = 'C:\drawings.csv'
$destcsv = 'C:\missing.csv'
Set-Location 'C:\test\'
Import-Csv $sourcecsv | ForEach {
Write-Output "${_} is the current object" #For Testing purpuse
$TK = $_.Tekeningnummer
If (Test-Path -Path $TK) {
Write-Output "$TK does exist"
} Else {
Write-Output "$TK doesnt exist"
$_ | Export-Csv $destcsv -Append -NoTypeInformation
}
}
not sure if ${_} is a new syntax I'm not aware of but I can't get it to work on my PS4 host so I'm changing that to the normal $_ in my answer. beyond that you just need to do an ExpandProperty as #DaveSexton suggests.
Import-Csv $sourcecsv | Select-object -ExpandProperty Tekeningnummer | ForEach {
Write-Output "$($_) is the current object" #For Testing purpuse
If (Test-Path -Path $($_) {
Write-Output "$($_) does exist"
} Else {
Write-Output "$($_) doesnt exist"
$_ | Export-Csv $destcsv -Append -NoTypeInformation
}
}
just do it ;)
$sourcecsv = 'C:\drawings.csv'
$destcsv = 'C:\missing.csv'
$dirtest='C:\test\'
Import-Csv $sourcecsv | where {-not (Test-Path "$dirtest$($_.Tekeningnummer)") } | export-csv $destcsv -NoTypeInformation

How do I modify this powershell script so it creates a log of the date time and names of all files that were deleted or previously deleted?

I wanted to make a PowerShell script that deleted any type of file in a certain folder when they were 7 days old. The problem I am having is creating a log file with the date, time, and names of all the files that were deleted or were previously deleted when the script ran.
I am wondering if there is a way of modifying the answer found on this page: https://stackoverflow.com/questions/12326171/powershell-script-to-delete-sub-folders-and-files-if-creation-date-is-7-days-bu?lq=1
I would like it so that instead of sending an email with the report it will create one log file of all the files deleted with the names, time, and dates in the folder that I am storing the script (Please note I'd like it to append the log file each time not overwrite it). I am sorry because I do not know how to code so I have been stuck trying to do this myself for a long time now and I have been asking questions and such but still can't seem to get it to work. So yea if anyone can modify that script it would be very appreciated! Thank you!
Here is what I did with the script (if it helps) , but it doesn't work (Again I do not know how to code):
$report_items = #()
# set folder path
$dump_path = "C:FileDeleter\AutoDeleteFilesInThisFolder"
# set min age of files
$max_days = "-7"
# get the current date
$curr_date = Get-Date
# determine how far back we go based on current date
$del_date = $curr_date.AddDays($max_days)
# get the sub directories
$sub_dirs = Get-ChildItem $dump_path | Where-Object {!$_.PSIsContainer }
$sub_dirs | % {
if (Get-ChildItem $_.FullName -Recurse | Where-Object { $_.LastWriteTime -gt $del_date } ) {
$report_items += New-Object -Type PSObject -Property #{
Time = Get-Date -f "hh:mm:ss"
Message = "Skipping " + $_.FullName + " because it contains items newer than " + $del_date
}
}
else {
Remove-Item $_.FullName -Recurse
$report_items += New-Object -Type PSObject -Property #{
Time = Get-Date -f "hh:mm:ss"
Message = "Deleting " + $_.FullName + " because it contains no items newer than " + $del_date
}
}
}
$report_items | out-file "C:\FileDeleter\PruningReport.txt"
This should do it:
Get-ChildItem -Path "C:\FileDeleter\AutoDeleteFilesInThisFolder" -Filter *.torrent -Recurse | Where { $_.CreationTime -lt (Get-Date).AddDays(-7) } | %{Remove-Item -Force; if ($?) {"$(Get-Date -Format 'MM-dd-yy HH:mm:ss.ff') $_.Name" | Add-Content 'C:\FileDeleter\PruningReport.txt'}}
(The reason for the if ($?) block is to only write a log entry if the file deletion was successful - you don't want to assume that it was.)
Not as succinct, but I'm a fan of not over-pipelining in PowerShell.
[String] $strBaseDir = "c:\temp";
[String] $strFileFilter = "*.txt";
[Int] $intDayThreshold = 7;
[System.IO.FileSystemInfo] $objFile = $null;
[Int] $intLastWriteDays = 0;
[String] $strLogFileName = "d:\data\yourlogfile.log";
Get-ChildItem -LiteralPath $strBaseDir -Filter $strFileFilter -Recurse | Where-Object{ ! $_.PSIsContainer } |
Foreach-Object {
$objFile = $_;
$intLastWriteDays = [Math]::Round((New-TimeSpan -Start $objFile.LastWriteTime -End (Get-Date)).TotalDays);
if ( $intLastWriteDays -ge $intDayThreshold ) {
Write-Output -InputObject ( "{0:G} : Deleting file [{1}] with last write time of [{2:G}], which is [{3}] day(s) ago." -f (Get-Date), $objFile.FullName, $objFile.LastWriteTime, $intLastWriteDays ) | Add-Content -Path $strLogFileName -PassThru;
$objFile | Remove-Item -Force -ErrorAction silentlyContinue;
if ( ! $? ) {
Write-Output -InputObject "ERROR : Failed to remove file." | Add-Content -Path $strLogFileName -PassThru;
} #if
} else {
Write-Output -InputObject ( "{0:G} : Skipping file [{1}] with last write time of [{2:G}], which is [{3}] day(s) ago." -f (Get-Date), $objFile.FullName, $objFile.LastWriteTime, $intLastWriteDays ) | Add-Content -Path $strLogFileName -PassThru;
} #else-if
} #Foreach-Object