Finding modified date of a file/folder - powershell

I am very new to PowerShell, and I was hoping I could get some help creating a script that tells me the modified date of a file.
I wish I knew more about PowerShell, as I feel like I am asking a lot (all my free-time this week will be dedicated to learning PowerShell better). Pointing me in the direction of where to learn how to do this would be very helpful as well.
Here is the complete rundown. I need to run a report daily that checks a list of computers at 90 different stores to make sure their a certain backup was performed. The modified date should tell if the backup had been performed, and will be set to the previous date.
If the modified date is yesterday, then there does not need to be an output. If it is not yesterday, I would like to have the output in the PowerShell window, or to a text file, whichever would be easier.
I also have to check that a folder is no older than seven days for each of the 90 stores, with the same criteria for the output. The idea that I have would be like this for each store
For Store 1:
Check file date for \\server\store\computer\c:\folder\"newest modified date in folder"
if date equals yesterday
then do nothing
if date does not equal yesterday
then output "Test did not backup"
check folder modified date for \\server\sample\store\backupfolder
if date equals <7 days old
then do nothign
if date equals >7 days old
then output "test did not backup"
Sorry for not proving my research effort, I am very new to Powershell and I was on a deadline to get this done. I have, since yesterday, learned how to do everything that I needed to do with this script. Thanks to #Keith for setting me on the correct path. I ended up using the following code to accomplish my goal of only out-putting the location where result was false.
$a = Get-ChildItem \\server\XXX\Received_Orders\*.* | Where{$_.LastWriteTime -ge (Get-Date).AddDays(-7)}
if ($a = (Get-ChildItem \\server\XXX\Received_Orders\*.* | Where{$_.LastWriteTime -ge (Get-Date).AddDays(-7)}))
{
}
Else
{
'STORE XXX HAS NOT RECEIVED ANY ORDERS IN THE PAST 7 DAYS'
}
$b = Get-ChildItem \\COMP NAME\Folder\*.* | Where{$_.LastWriteTime -ge (Get-Date).AddDays(-1)}
if ($b = (Get-ChildItem \\COMP NAME\TFolder\*.* | Where{$_.LastWriteTime -ge (Get-Date).AddDays(-1)}))
{
}
Else
{
'STORE XXX DID NOT RUN ITS BACKUP LAST NIGHT'
}

If you run the Get-Item or Get-ChildItem commands these will output System.IO.FileInfo and System.IO.DirectoryInfo objects that contain this information e.g.:
Get-Item c:\folder | Format-List
Or you can access the property directly like so:
Get-Item c:\folder | Foreach {$_.LastWriteTime}
To start to filter folders & files based on last write time you can do this:
Get-ChildItem c:\folder | Where{$_.LastWriteTime -gt (Get-Date).AddDays(-7)}

To get the modified date on a single file try:
$lastModifiedDate = (Get-Item "C:\foo.tmp").LastWriteTime
To compare with another:
$dateA= $lastModifiedDate
$dateB= (Get-Item "C:\other.tmp").LastWriteTime
if ($dateA -ge $dateB) {
Write-Host("C:\foo.tmp was modified at the same time or after C:\other.tmp")
} else {
Write-Host("C:\foo.tmp was modified before C:\other.tmp")
}

Here's what worked for me:
$a = Get-ChildItem \\server\XXX\Received_Orders\*.* | Where{$_.LastWriteTime -ge (Get-Date).AddDays(-7)}
if ($a = (Get-ChildItem \\server\XXX\Received_Orders\*.* | Where{$_.LastWriteTime -gt (Get-Date).AddDays(-7)}
#Im using the -gt switch instead of -ge
{}
Else
{
'STORE XXX HAS NOT RECEIVED ANY ORDERS IN THE PAST 7 DAYS'
}
$b = Get-ChildItem \\COMP NAME\Folder\*.* | Where{$_.LastWriteTime -ge (Get-Date).AddDays(-1)}
if ($b = (Get-ChildItem \\COMP NAME\TFolder\*.* | Where{$_.LastWriteTime -gt (Get-Date).AddDays(-1)))}
{}
Else
{
'STORE XXX DID NOT RUN ITS BACKUP LAST NIGHT'
}

You can try dirTimesJS.bat and fileTimesJS.bat
example:
C:\>dirTimesJS.bat %windir%
directory timestamps for C:\Windows :
Modified : 2020-11-22 22:12:55
Modified - milliseconds passed : 1604607175000
Modified day of the week : 4
Created : 2019-12-11 11:03:44
Created - milliseconds passed : 1575709424000
Created day of the week : 6
Accessed : 2020-11-16 16:39:22
Accessed - milliseconds passed : 1605019162000
Accessed day of the week : 2
C:\>fileTimesJS.bat %windir%\notepad.exe
file timestamps for C:\Windows\notepad.exe :
Modified : 2020-09-08 08:33:31
Modified - milliseconds passed : 1599629611000
Modified day of the week : 3
Created : 2020-09-08 08:33:31
Created - milliseconds passed : 1599629611000
Created day of the week : 3
Accessed : 2020-11-23 23:59:22
Accessed - milliseconds passed : 1604613562000
Accessed day of the week : 4

PowerShell code to find all document library files modified from last 2 days.
$web = Get-SPWeb -Identity http://siteName:9090/
$list = $web.GetList("http://siteName:9090/Style Library/")
$folderquery = New-Object Microsoft.SharePoint.SPQuery
$foldercamlQuery =
'<Where> <Eq>
<FieldRef Name="ContentType" /> <Value Type="text">Folder</Value>
</Eq> </Where>'
$folderquery.Query = $foldercamlQuery
$folders = $list.GetItems($folderquery)
foreach($folderItem in $folders)
{
$folder = $folderItem.Folder
if($folder.ItemCount -gt 0){
Write-Host " find Item count " $folder.ItemCount
$oldest = $null
$files = $folder.Files
$date = (Get-Date).AddDays(-2).ToString(“MM/dd/yyyy”)
foreach ($file in $files){
if($file.Item["Modified"]-Ge $date)
{
Write-Host "Last 2 days modified folder name:" $folder " File Name: " $file.Item["Name"] " Date of midified: " $file.Item["Modified"]
}
}
}
else
{
Write-Warning "$folder['Name'] is empty"
}
}

Related

How to download an Outlook attachments based on specific file name within the 24 hrs?

I'm trying to download attachments within emails based on file name that have been received within the last 24 hour AND are the first match. The first match is in-case a second email with the same filename is received and needed to be output to the location. The files are received to the inbox typically once a day but there are times where it'll have to be handled via the 'latest received'. So wit that said, when there is a match, the code supposed to grab the files and put the first matched files to the location and then stop / terminate the script.
However, it doesn't seem to take the time factor into account at all. At this point my code finds the first matched two files based on the filename, and dumps them into the location. Then it keeps overwriting the files as it finds older files with the same name within the inbox.
In this latest build / attempt, I'm using $limit = (Get-Date).AddDays(-1) as well as -and ($_.CreationTime -lt $limit) in my code. I've tried a number of methods but nothing seems to work.
$account = 'blah#stihlse.com'
$targetFolder = 'inbox'
$f = $account.Folders | ? { $_.Name -match 'inbox'};
$email = $f.Items| Sort-Object ReceivedTime -Descending | Select-Object -First 1
$limit = (Get-Date).AddDays(-1)
$filepath = "\\servername\home\blah\Documents\blah's emails"
$ol = New-Object -comobject outlook.application
$ns = $ol.GetNamespace('MAPI')
$acct = $ns.Folders[$account]
$acct.Folders[$targetFolder].Items | foreach {
if ($_.ReceivedTime -match $email -and ($_.CreationTime -eq $limit)) {
$_.attachments |
foreach {
Write-Host "attached file: ",$_.filename
If ($_.filename -match 'BlahCompletions' -or $_.filename -match 'BlahCertifications'){
$_.saveasfile((Join-Path $filepath $_.FileName))
}
}
}
}
You use CreationTime -eq $limit. -eq means equal. So it only works if the CreationTime is the exact same microsecond as $limit. What you are looking for is -gt (greater than) or -ge (greater or equal).
The other problem is $_.ReceivedTime -match $email. It is trying to -match the ReceivedTime to an regex. But the regex you provide is the whole $email. Take a look at about_Comparison_Operators
In the code you are iterating over all items in the folder:
$acct.Folders[$targetFolder].Items | foreach {
if ($_.ReceivedTime -match $email -and ($_.CreationTime -eq $limit)) {
Which is really is not a good idea if you have a large number items in the folder. Instead, you need to use the Find/FindNext or Restrict methods of the Items class. Read more about these methods in the following articles:
How To: Use Find and FindNext methods to retrieve Outlook mail items from a folder (C#, VB.NET)
How To: Use Restrict method to retrieve Outlook mail items from a folder
For example, to get only items that has attachments onboard you can use the following condition:
query ="#SQL=" & chr(34) & "urn:schemas:httpmail:hasattachment" & chr(34) & "=1"

powershell date comparision need to delete file

i have to make powershell file where i need to compare 2 dates and delete folder which is like more than 10 days of last write item . like today is 30 October i need to delete folder where comparision of dates give 11 12 and 13 days
#ChildItem "\\server\Backup" -Recurse | Where-Object {$_.LastWriteTime -gt (Get-Date).AddDays.(-30) }
#$fulllist =Get-ChildItem "\\server\Backup\SharePoint Backup\"| Where-Object {$_.LastWriteTime -gt (Get-Date).AddDays.(5) }
$fulllist =Get-ChildItem "\\server\Backup\SharePoint Backup\"
#$fulllist =Get-ChildItem "\\server\Backup\SharePoint Backup\" -Recurse | Where-Object {$_.LastWriteTime -gt (Get-Date).AddDays.(-20) }
foreach ($fileitem in $fulllist)
{
$filename_big = $fileitem.FullName
#write-host $filename_big
$d = [datetime](Get-ItemProperty -Path $filename_big -Name LastWriteTime).lastwritetime
$d1=(get-date)
#write-host $d
#write-host $d1
$ts = New-TimeSpan -Start $d -End $d1
$ts.Days # Check results\
write-host $ts
if($ts -gt 10)
{
write-host "inside"
}
# Move-Item -Path $filename_big -Destination "\\DBORION\d$\backup"
}
iam comparing two dates $d & d1 and days are greater than 10 that folders should get deleted.
but with output iam getting its going inside for all folders whether its 10 days or 5 days ,please find output
0
00:58:29.2923431
inside
0
13:33:32.4388907
inside
0
07:02:28.0900378
inside
0
03:52:35.3425970
inside
0
00:58:29.4017400
inside
13
13.08:49:05.4930775
inside
12
12.08:49:06.3403154
inside
11
11.08:48:31.4681438
inside
10
10.08:48:18.6859604
inside
9
9.08:49:01.2220544
inside
8
8.08:39:56.7230423
inside
7
7.08:48:15.3242000
inside
6
6.08:49:03.6123002
inside
5
5.08:49:08.5439345
inside
4
4.08:49:06.6188386
inside
3
3.08:49:07.2066345
inside
2
2.08:49:06.2290185
inside
1
1.08:45:07.0454477
inside
0
08:47:24.1939025
inside
ok so i got this
$fulllist = Get-ChildItem "\\Server\Backup\SharePoint Backup\"
$Days = 12
foreach ($fileitem in $fulllist)
{
$filename_big = $fileitem.FullName
$deletedate = (Get-Date).AddDays(-$Days)
$Folderdate = [datetime](Get-ItemProperty -Path $filename_big -Name LastWriteTime).lastwritetime
if($Folderdate -le $deletedate)
{
$filename_big
Remove-Item -Path $filename_big -Force -Confirm:$false
}
}
now my only concern is its asking for confirmation of deletion, i dont want that popup box how to bypass that
I think the problem is that your variable $ts is a timespan. A timespan can never be greater then 10, because it is a number. In your if clause you should use:
if($ts.Days -gt 10)
And some other maybe needfull advices to spare some byte:
when you define your $d variable, this can be done much shorter: $d = $fileitem.lastwritetime - the $fileitem variable itself has the lastwritetime property.
when assigning a function to a variable, there is no need for round brackets: just use $d1 = Get-Date. The brackets are only needed if you want to assign a propery of the function, for example $d = (Get-Date).DayOfWeek.
you could avoid creating the timespan by this: if($d -gt $d1.addDays(-10)). This compares your file timestamp $d with the current time minus 10 days, meaning the point in time exactly 10 days ago.
And to bypass confirmation when you delete files: use the -force parameter.

How to compare to string in PowerShell foreach loop to files

How to compare the current month with file modified in current month using power shell script. My code is working file but it is reading all the csv file in the given directory. I just wanted to read current month file i.e. modified in October 2018.
Please help me out , I have total 6 files in my directory. 3 files having date modified in October 2018 and remaining 3 files are modified in September 2018.
I want my script to check the current month then read all csv of current month i.e. October 2018
Code:
$files = Get-ChildItem 'C:\Users\212515181\Desktop\Logsheet\*.csv'
$targetPath = 'C:\Users\212515181\Desktop\Logsheet'
$result = "$targetPath\Final.csv"
$curr_month = (Get-Date).Month
$curr_year = (Get-Date).Year
# Adding header to output file
[System.IO.File]::WriteAllLines($result,[System.IO.File]::ReadAllLines($files[1])[1])
foreach ($file in $files)
{
$month = $file.LastWriteTime.ToString()
$curr_month=(Get-Date).Month
if ($month= $curr_month)
{
$firstLine = [System.IO.File]::ReadAllLines($file) | Select-Object -first 1
[System.IO.File]::AppendAllText($result, ($firstLine | Out-String))
$lines = [System.IO.File]::ReadAllLines($file)
[System.IO.File]::AppendAllText($result, ($lines[2..$lines.Length] | Out-String))
}
}
# Change output file name to reflect month and year in MMYYYY format
Rename-Item $result "Final_$curr_month$curr_year.csv"
Your comparison is wrong. And will return $true causing all files to be read
It should be
if ($month -eq $curr_month)
Also I would remove the second
$curr_month = (get-date).month
it's adding overhead to your script as you set it before the loop

Compare current date to date string in a file using powershell

I am writing some PS scripts to log times into a text file, login.txt, using the following code:
$logdir = "C:\FOLDER"
$logfile = "$logdir\LastLogin.txt"
$user = $env:USERNAME
$date = Get-Date -Format "dd-MM-yyyy"
if (!(Test-Path $logdir)){New-Item -ItemType Directory $logdir}else{}
if (!(Test-Path $logfile)){New-Item $logfile}else{}
if (Get-Content $logfile | Select-String $user -Quiet){write-host "exists"}else{"$user - $date" | Add-Content -path $logfile}
(Get-Content $logfile) | Foreach-Object {$_ -replace "$user.+$", "$user - $date"; } | Set-Content $logfile
This creates an entry in the text file like:
UserName - 01-01-1999
Using Powershell, I want to read the text file, compare the date, 01-01-1999, in the text file to the current date and if more than 30 days difference, extract the UserName to a variable to be used later in the script.
I would really appreciate any hints as to how I could do the following:
Compare the date in the text file to the current date.
If difference is more than 30 days, pick up UserName as a variable.
I would really appreciate any advice.
Checking all dates in the file with the help of a RegEx with named capture groups.
$logdir = "C:\FOLDER"
$logfile = Join-Path $logdir "LastLogin.txt"
$Days = -30
$Expires = (Get-Date).AddDays($Days)
Get-Content $logfile | ForEach-Object {
if ($_ -match "(?<User>[^ ]+) - (?<LastLogin>[0-9\-]+)") {
$LastLogin = [datetime]::ParseExact($Matches.LastLogin,"dd-MM-yyyy",$Null)
if ( $Expires -gt $LastLogin ) {
"{0} last login {1} is {2:0} days ago" -F $Matches.User, $Matches.LastLogin,
(New-TimeSpan -Start $LastLogin -End (Get-Date) ).TotalDays
}
}
}
Sample output
username last login 31-12-1999 is 6690 days ago
There is a way of doing that using regex (Regular Expressions). I will assume that the username which you get in your text file is .(dot) separated. For example, username looks like john.doe or jason.smith etc. And the entry in your text file looks like john.doe - 01-01-1999 or jason.smith - 02-02-1999. Keeping these things in mind our approach would be -
Using a regex we would get the username and date entry into a single variable.
Next up, we will split the pattern we have got in step 1 into two parts i.e. the username part and the date part.
Next we take the date part and if the difference is more than 30 days, we would take the other part (username) and store it in a variable.
So the code would look something like this -
$arr = #() #defining an array to store the username with date
$pattern = "[a-z]*[.][a-z]*\s[-]\s[\d]{2}[-][\d]{2}[-][\d]{4}" #Regex pattern to match entires like "john.doe - 01-01-1999"
Get-Content $logfile | Foreach {if ([Regex]::IsMatch($_, $pattern)) {
$arr += [Regex]::Match($_, $pattern)
}
}
$arr | Foreach {$_.Value} #Storing the matched pattern in $arr
$UserNamewithDate = $arr.value -split ('\s[-]\s') #step 2 - Storing the username and date into a variable.
$array = #() #Defining the array that would store the final usernames based on the time difference.
for($i = 1; $i -lt $UserNamewithDate.Length;)
{
$datepart = [Datetime]$UserNamewithDate[$i] #Casting the date part to [datetime] format
$CurrentDate = Get-Date
$diff = $CurrentDate - $datepart
if ($diff.Days -gt 30)
{
$array += $UserNamewithDate[$i -1] #If the difference between current date and the date received from the log is greater than 30 days, then store the corresponding username in $array
}
$i = $i + 2
}
Now you can access the usernames like $array[0], $array[1] and so on. Hope that helps!
NOTE - The regex pattern will change as per the format your usernames are defined. Here is a regex library which might turn out to be helpful.

powershell delete some files older than 90 days, with exceptions

$timeLimit1 = Get-Date.AddDays(-90)
Get-ChildItem <path> | ? {$_.LastWriteTime -le $timeLimit1 } | Remove-Item
So I have the easier part, but I am trying to figure out how to do something a little more complex.
I am setting up a backup deletion routine. The requirement is to keep the last 90 days of backups, then the final day of each month prior to that for the current year and finally a backup from December 31st for the prior 2 years.
I couldn't find any examples other than just a single check; is it possible to do several checks to automate that.
I suggest writing a custom filter to apply the logic e.g.
filter MyCustomFilter{
$File = $_
$FileDate = $File.LastWriteTime
$Now = (Get-Date)
$FileAgeDays = ($Now - $FileDate).TotalDays
if (
# Keep files for at least 90 days
( $FileAgeDays -lt 91
) -or
# Keep files from last day of the month this year
( $FileDate.Year -eq $Now.Year -and
$FileDate.Month -ne $FileDate.AddDays(1).Month
) -or
# Keep files from 31 Dec for up to 2 years
( $FileAgeDays -lt ( 2 * 365 ) -and
$FileDate.Month -eq 12 -and
$FileDate.Day -eq 31
)
) {
# File should be kept, so nothing is returned by the filter
} else {
# File should be deleted, so pass the file down the pipeline
write-output $File
}
}
Now your overall code would look something like this:
get-childItem -path <path> |
where-object { -not $_.PSIsContainer } |
MyCustomFilter |
Remove-Item
It goes without saying, that proper testing is required before letting this loose on production systems.
EDIT: A Simpler test for last day of month
I thought of a neater 'last day of the month' test, which is simply to compare the month property of the date under test, with the month property of the following day e.g.
$FileDate.Month -ne $FileDate.AddDays(1).Month
will return $true if $FileDate is last day of the month.
Just create an array of your "special" dates and add them to your filter.
$timeLimit1 = Get-Date
$timeLimit1.AddDays(-90)
$specialDates = (Get-Date "31-12-2014"), (Get-Date "31-05-2017") # continue the list
Get-ChildItem <path> | ? {$_.LastWriteTime -le $timeLimit1 -and $specialDates -notcontains $_.LastAccessTime.Date } | Remove-Item
I would also make a function to find the "special" dates.