我有一个备份脚本,该脚本每天晚上都将文件放入带日期的目录中。我在下面还有另一个脚本,该脚本遍历了带日期的目录,如果它在我要删除的范围内,我将删除该目录,并保留周六的日期文件。由于某些原因,对于日期为2019年1月12日星期六的目录,即使if语句应指示不会删除它,该目录也会被删除。
这是我的代码:
function WeeklyCleanup($folderWeeklyCleanupDatedSubdirs) {
#find out date range to cleanup
$lastSaturday = GetLastSaturdayDate
$lastSaturday = [datetime]$lastSaturday
$weekAgoSunday = GetWeekAgoSundayDate
$weekAgoSunday = [datetime]$weekAgoSunday
#find out filename with Saturday date before current date but within week
Get-ChildItem $folderWeeklyCleanupDatedSubdirs | ForEach-Object {
write-output $_
#check to see if item is before day we want to remove
$temp = $_
$regex = [regex]::Matches($temp,'([0-9]+)-([0-9]+)-([0-9]+)')
if($regex.length -gt 0) #it matched
{
$year = $regex[0].Groups[1].Value
$month = $regex[0].Groups[2].Value
$day = $regex[0].Groups[3].Value
write-output $year
write-output $month
write-output $day
write-output "*************"
$dirDate = $regex[0].Groups[0].Value + " 12:00:00 PM"
write-output $dirDate
if($dirDate.length -gt 0) #it matched
{
$dateTimeObjectFromRegex = [datetime]$dirDate
##########此下一条语句让$ dateTimeObjectFromRegex of 1/12/2019通过不该通过的时间。请参阅下面的时间比较
if(([datetime]$dateTimeObjectFromRegex -lt [datetime]$lastSaturday) -and ([datetime]$dateTimeObjectFromRegex -ge [datetime]$weekAgoSunday)) #we're removing extra ones over last week, keep Saturday
{
$dirPathToRemove = Join-Path -path $folderWeeklyCleanupDatedSubdirs -ChildPath $temp.ToString()
Get-ChildItem -Path $dirPathToRemove #list the dir
#remove dir
if(-Not (Test-Path $dirPathToRemove )) #-PathType Container
{
$global:ErrorStrings.Add("Exception: No such path, $dirPathToRemove;; ")
write-output "++ Error: An error occured during copy operation. No such path, $dirPathToList ++"
}
else
{
#remove dir and subdirs
Remove-Item $dirPathToRemove -Force -Recurse
Get-ChildItem -Path $dirPathToRemove #list the dir
}
#Write-Output $_
#Write-Output " 1 "
} #if within last week
} #if dirDate length
} #if regex matched
} #get-childItem
}
function GetLastSaturdayDate()
{
$date = Get-Date #"$((Get-Date).ToString('yyyy-MM-dd'))"
#for($i=1; $i -le 7; $i++){
# if($date.AddDays(-$i).DayOfWeek -eq 'Saturday') #if found Saturday
# {
# $date.AddDays(-$i)
# $newDate = $date.AddDays(-$i)
# break
# }
#}
$newdate = $date.AddDays(-($date.DayOfWeek+1)%7)
return $newdate
}
function GetWeekAgoSundayDate()
{
$numberOfWeeks = 1; #week ago
$date = Get-Date #"$((Get-Date).ToString('yyyy-MM-dd'))"
#for($i=1; $i -le 7; $i++){
# if(($date.AddDays(-$i).DayOfWeek -eq 'Sunday') -and ($date.AddDays(-$i) -ne $date)) #if found a Sunday and it's not today
# {
# $date.AddDays(-$i)
# $newDate = $date.AddDays(-$i)
# break
# }
#}
#$newdate = $date.AddDays(-($date.DayOfWeek+1)%0)
$numDaysSincePreviousDate = $date.DayOfWeek.value__ + 0 #0 is Sunday
([System.DateTime] $previousDayOfWeek = $date.AddDays(- $numDaysSincePreviousDate)) | Out-Null
$previousDate = $previousDayOfWeek.AddDays(-($numberOfWeeks *7)).ToString("MM-dd-yyyy")
return $previousDate
}
使用以下参数调用WeeklyCleanup脚本:
$folderToCleanupDatedSubdirs = [System.IO.DirectoryInfo]"E:\Bak_TestDatedFolderCleanup"
用于时间比较:
Directory项目到LocRobo_2019-01-12-一旦获得带有时间戳的正则表达式,就为$ dirDate变量添加了12:00:00 PM的时间。这将变成$ dateTimeObjectFromRegex。调试器将其显示为2019年1月12日(星期六)下午12:00:00
运行程序时,我将在2019年1月12日星期六下午3:59:04收到$ lastSaturday
当我运行程序时,调试器还将$ weekAgoSunday显示为2019年1月6日星期日12:00:00 AM
从我所看到的,应该不应该通过if语句删除2019年1月12日的目录。
我尝试将日期强制转换为日期时间,以确保即使在上面强制转换,也不会在if语句中进行字符串比较。
我一直在寻找这些链接,以获取有关此的更多信息,但对我来说似乎是正确的:
dateTimeComparisons not working expectedly
我能想到的是,它仍将if语句比较的第一部分中的日期时间像字符串一样对待,因此它认为3:59 PM大于12:00 PM。任何想法如何使此日期检查工作?我不在乎时间,只是想确保它不会清除过去一周的星期六日期文件,而是仅清除该周的其他目录。
更新 进行了以下@brianist建议的更改,效果很好。到目前为止是这样。周六和周日功能未更改。他要我发布。如果他还有其他建议如何使用它来处理/比较上周六和周从周六返回的内容,而没有转换,则AgoSunday看起来不那么笨拙/更容易阅读。谢谢布莱恩!
#do weekly cleanup of DisasterBackup folder
function WeeklyCleanup($folderWeeklyCleanupDatedSubdirs) {
#find out current date
$currentDate = "$((Get-Date).ToString('yyyy-MM-dd'))" #example 2019-01-15
$currentDayOfWeek = (get-date).DayOfWeek.value__ #returns int value for day of week
#find out current day of week
$lastSaturday = GetLastSaturdayDate
$lastSaturday = [datetime]$lastSaturday #if we take away extra casts it won't do comparison line (-lt and -ge)
$weekAgoSunday = GetWeekAgoSundayDate
$weekAgoSunday = [datetime]$weekAgoSunday #if we take away extra casts it won't do comparison line (-lt and -ge), and can't move cast before function call because it isn't recognizing function anymore if I do
#find out filename with Saturday date before current date but within week
#get each dir item to check if we need to remove it
Get-ChildItem $folderWeeklyCleanupDatedSubdirs | ForEach-Object {
write-output $_
#check to see if item is before day we want to remove
$temp = $_
if($_.Name -match '(\d{4}-\d{2}-\d{2})$'){ #regex
write-output $Matches[1]
$dirDate = Get-Date $Matches[1] #turn regex into date
if(([datetime]$dirDate.Date -lt [datetime]$lastSaturday.Date) -and ([datetime]$dirDate.Date -ge [datetime]$weekAgoSunday.Date)) #we're removing extra ones over last week, keep Saturday
{
$dirPathToRemove = Join-Path -path $folderWeeklyCleanupDatedSubdirs -ChildPath $temp.ToString()
Get-ChildItem -Path $dirPathToRemove #list the dir
#remove dir
if(-Not (Test-Path $dirPathToRemove )) #-PathType Container
{
$global:ErrorStrings.Add("Exception: No such path, $dirPathToRemove;; ")
write-output "++ Error: An error occured during copy operation. No such path, $dirPathToList ++"
}
else
{
#remove dir and subdirs
Remove-Item $dirPathToRemove -Force -Recurse
Get-ChildItem -Path $dirPathToRemove #list the dir
}
} #if within last week
} #if regex matched
} #get-childItem
}
答案 0 :(得分:1)
重新阅读您的最后一句话,我现在看到您的意图是忽略时间,而不是将它们包括在比较中。
比较时,您想使用[DateTime]
对象是正确的,但请注意,这些对象始终包含一个时间。
您可以方便地使用此类对象的.Date
属性,该属性返回一个新的对象,时间设置为午夜。这对于进行比较很有用,因为时间不再是一个因素。
从下面拉出我修改过的if
语句,您可以这样做:
if ($dirDate.Date -lt $lastSaturday.Date -and $dirDate.Date -ge $weekAgoSunday.Date) {
# do stuff
}
现在您只比较日期,而忽略时间!
根据您所显示的内容,if
语句似乎可以正常工作。总而言之,您说:
$dateTimeObjectFromRegex
是Saturday, January 12, 2019 12:00:00 PM
$lastSaturday
是Saturday, January 12, 2019 3:59:04 PM
$weekAgoSunday
是Sunday, January 6, 2019 12:00:00 AM
条件是:
if(([datetime]$dateTimeObjectFromRegex -lt [datetime]$lastSaturday)
-and ([datetime]$dateTimeObjectFromRegex -ge [datetime]$weekAgoSunday))
因此,用伪代码是:
if (
("January 12, 2019 12:00:00 PM" is earlier than "January 12, 2019 3:59:04 PM") # true
and
("January 12, 2019 12:00:00 PM" is later or the same as "January 6, 2019 12:00:00 AM") # true
) # true
我确实要指出,您正在做很多不必要的日期时间裁剪和转换,清理这些内容将有助于提高可读性并调试这些类型的问题。
$lastSaturday = GetLastSaturdayDate
$lastSaturday = [datetime]$lastSaturday
$weekAgoSunday = GetWeekAgoSundayDate
$weekAgoSunday = [datetime]$weekAgoSunday
您的函数已经返回了[DateTime]
个对象,因此不需要这些强制类型转换。
$temp = $_
$regex = [regex]::Matches($temp,'([0-9]+)-([0-9]+)-([0-9]+)')
if($regex.length -gt 0) #it matched
{
$year = $regex[0].Groups[1].Value
$month = $regex[0].Groups[2].Value
$day = $regex[0].Groups[3].Value
write-output $year
write-output $month
write-output $day
write-output "*************"
$dirDate = $regex[0].Groups[0].Value + " 12:00:00 PM"
write-output $dirDate
这非常复杂,您可以将其简化为以下形式:
if ($_.Name -match '(\d{4}-\d{2}-\d{2})$') {
# in here, you know the match was successful
$dirDate = Get-Date $Matches[1] # double check this, might need .Groups or something
if ($dirDate -lt $lastSaturday -and $dirDate -ge $weekAgoSunday) {
# do stuff
}
}
可能还有更多优化等。希望对您有所帮助!