此代码在Powershell 5+中运行良好,但在Powershell 4.0和2.0中不起作用:
$DaysToDelete = 2
$targets = "profile/Default",
"profile/Profile 1",
"profile/Profile 2",
"profile/Profile 3",
"profile/Profile 4"
$special = @("chromium", "64")
$profiles = Get-ChildItem "C:\" -Directory -Force |
Where-Object Name -In $special |
Select-Object -ExpandProperty FullName
$chromeDir = "C:\Users\*\AppData\Local\Google\Chrome\User Data\Default"
$chromeSetDir = "C:\Users\*\Local Settings\Application Data\Google\Chrome\User Data\Default"
$Items = @("*Archived History*",
"*Cache*",
"*Cookies*",
"*History*",
"*Top Sites*",
"*Visited Links*",
"*Web Data*")
$profiles | ForEach-Object {
foreach($target in $targets) {
$profile = Join-Path $_ $target
$items | ForEach-Object {
$item = $_
Get-ChildItem $profile, $chromeDir, $chromeSetDir -Recurse -Force -ErrorAction SilentlyContinue |
Where-Object { ($_.CreationTime -lt $(Get-Date).AddDays(-$DaysToDelete)) -and $_.Directory -like $item} | ForEach-Object {
$path = Join-Path $_.DirectoryName $_
Remove-Item $path -force -Verbose -recurse -ErrorAction SilentlyContinue }
}
}
}
我透露,打破执行的那块是
-and $_.Directory -like $item
它在PS 5+(Windows 10)上工作正常但在PS 4(Windows 7)上没有发现任何相似的模式。 Chrome版本及其目录层次结构在两台计算机上都相同: 59.0.3071.115(官方版本)(64位)。
在Win10上启动脚本,版本规范相似
powershell.exe -Version 4.0
什么都没有,它运行得很好。
我对Powershell版本的细节不太熟悉,欢迎大师提出任何建议。 如何使脚本独立于版本?
更新: Here is完整代码,但它没有任何价值。我验证了所有地方,并确切地说明了上面的问题行。
另一个有趣的时刻:我发现问题本身不在like
子句中,而在like
和$_.CreationTime
的组合中检查:< / p>
$_.CreationTime -lt $(Get-Date).AddDays(-$DaysToDelete) -and $_.Directory -like $item
如果我单独放置其中任何一个条件,一切正常,但是如果我将它们组合成单一复合条件,则不会返回任何内容,但 文件夹符合这两个条件。
我无法以任何方式解释这一点。
答案 0 :(得分:4)
我在评论中提到过这一点;我不确定它是否足够清楚,以及这是否是整个问题。
根据您的原始问题,此行不起作用。这不依赖于PowerShell版本。
$_.Directory -like $item
当Get-ChildItem
找到文件时,它会返回System.IO.FileInfo
class个对象。
Directory
是FileInfo
类的属性,因此文件将具有此属性。Directory
属于DirectoryInfo
。当Get-ChildItem
找到文件夹/目录时,它将返回System.IO.DirectoryInfo
class个对象。
DirectoryInfo
个对象没有Directory
属性。Parent
,还会返回System.IO.DirectoryInfo
个对象在任何一种情况下,您都在处理一个对象并将其与字符串进行比较。当你真的想要将文件夹名称与字符串进行比较时
对于运行v5.1.14409.1005
的Windows 8.1,修改为True;对于较旧的操作系统,期望是相同的
运行PS v5.1.143993.1480
的Windows 10为False;期望在Server 2016上保持不变。不确定Name
/ FullName
属性是如何自动评估的......
Get-ChildItem -File | Where {$_.Directory -like "*test*"} # not ok: comparing object to string.
Get-ChildItem -Directory | Where {$_.Directory.Name -like "*test*"} # not ok: DirectoryInfo object does not have Directory property
Get-ChildItem -File | Where {$_.Directory.Name -like "*test*"} # ok
Get-ChildItem -Directory | Where {$_.Parent.Name -like "*test*"} # ok
答案 1 :(得分:2)
如何使脚本与版本无关?
对我而言,如何使其与版本无关的最佳方法是使用您需要支持的最低版本,在您的情况下为2.0。
另一个选项是检测PowerShell版本并使您的版本彼此独立。
我查看了你的剧本
我建议在实际删除项目之前使用Test-Path -Path "$var"
工具来测试结果的有效性。
现在要真正解决您的问题: 在使用PowerShell和清除用户配置文件时,我遇到了类似的问题。
针对您的具体情况进行调整(通过like
来解决您的问题):
$newer_file_exist += Get-ChildItem -Path $profile -Recurse -Force -ErrorAction SilentlyContinue | Where-Object {$_.PSIsContainer -eq $FALSE} | where {($_.CreationTime).ToString('yyyy-MM-dd') -lt (get-date).adddays(-$DaysToDelete).ToString('yyyy-MM-dd')};
它将选择比-$DaysToDelete
更新的所有文件。它将递归并仅选择文件{$_.PSIsContainer -eq $FALSE}
。如果你想选择目录`{$ _.PSIsContainer -eq $ TRUE}。
# get all files to be deleted
ForEach ($dir in $profiles_with_path) {
# to check
$test_current_pathPath = Test-Path -Path $dir
If ($test_current_pathPath) {
#write-host 'Currently writing for these months:'$($time.Name);
$files_to_delete += Get-ChildItem -Path $dir -recurse -Force | Where-Object {$_.PSIsContainer -eq $FALSE} | % { $_.FullName }
}
}
要删除文件:
If ($files_to_delete) {
ForEach ($file in $files_to_delete) {
#Remove-Item $file -Recurse -Force -ErrorAction SilentlyContinue
Remove-Item $file -Force -ErrorAction SilentlyContinue
If ($? -eq $true) {
$files_deleted ++;
#Write-Verbose -Verbose "$File deleted successfully!"
}
}
和
所有目录
ForEach ($dir in $profiles_with_path) { #
Remove-Item $dir -Recurse -Force -ErrorAction SilentlyContinue
If ($? -eq $true) {
$directories_deleted ++;
#Write-Verbose -Verbose "$File deleted successfully!"
}
}
这些代码段适用于2.0(在WinXP和Windows 2003(SPx)以及4.0 Win7测试中测试过。
首次编辑:
我试图为你选择有效的代码,但显然我可以做得更好。 逻辑如下:我想删除所有不包含任何3个月以上文件的配置文件。
变量$newer_file_exist
- 用于指示是否找到此类文件。如果找到了
已跳过整个个人资料 - 已添加到$excluded_directories.Add($profile)
(有关详情,请参阅源代码链接)
$profiles_with_path
填充了 - $profiles_with_path = Get-ChildItem -Path $folder_to_cleanse -exclude $excluded_directories | Where-Object {$_.PSIsContainer -eq $True}
我从$excluded_directories
这是我在BB上公开的剧本: The whole source code on my BB (它包括测试运行逻辑,时间规范等)