我想在所有分区中找到所有.txt文件,但我不想在C:\ Windows,C:\ PerfLogs等文件夹中查找...
我的代码不起作用。
$exl = ("*\PerfLogs\*","*\Program Files*","*\ProgramData\*","*\Windows\*",":\Python*");
foreach($i in (Get-PSDrive).Name -match '^[a-z]$'){
foreach($item in (Get-ChildItem "${i}:\*.txt" -Recurse | Where {$_.FullName -notlike $exl})) {
echo $item.Fullname;}}
请提高我的代码资源效率。使其完全跳过排除的文件夹,而无需递归到它们。
奇怪的是,我只用1个元素运行它,但它仍然无法正常工作。
foreach($i in (Get-PSDrive).Name -match '^[a-z]$'){ foreach($item in (Get-ChildItem "${i}:\*.txt" -Recurse | Where-Object {$_.FullName -NotLike "Windows"})) { echo $item.Fullname;}}
它仍然在C:\中打印所有txt文件,它会忽略该异常。
我尝试在 Windows 一词周围使用通配符,但没有通配符,结果仍然相同。
还尝试了-NotContains,-NotIn ....
请您自己运行命令并亲自查看
答案 0 :(得分:3)
-like
和-notlike
运算符仅支持单模式作为RHS,不支持数组 < sup> [1] ,所以$_.FullName -notlike $exl
不会按您期望的那样工作。
(它将通过使用单个空格作为分隔符来连接数组元素,从而将数组$exl
转换为单个字符串。
您可以将switch
语句与-wildcard
选项一起使用:
$driveRoots = (Get-PSDrive -PSProvider FileSystem).Root
Get-ChildItem -Recurse $driveRoots -Filter *.txt | Where-Object {
switch -wildcard ($_.FullName) {
'*\PerfLogs\*' { break }
'*\Program Files*' { break }
'*\ProgramData\*' { break }
':\Python*' { break }
default { return $True } # doesn't match exclusion -> include
}
return $False # matches exclusion -> exclude
}
尽管此解决方案不会阻止递归到与模式匹配的文件夹中,但使用-Filter
参数通过使文件系统提供程序执行初始筛选可以大大减少扫描工作。
[1]长期存在但苦恼的feature request on GitHub也使-like
/ -notlike
也可以处理模式数组。
答案 1 :(得分:0)
我不确定这是否是问题的100%,但如果我记得逗号在PowerShell中可以创建can数组。
,
逗号运算符
作为二进制运算符,逗号创建一个数组。作为一元运算符,逗号创建一个包含一个成员的数组。将逗号放在成员之前。
出于故障排除的目的,您可以只尝试1个目录,而$ exl变量中没有任何逗号吗?
答案 2 :(得分:0)
很少观察到
-NotLike "Windows" #you forgot *, this will only be false when item name is "Windows"
-notlike $exl # not like with array will always return true
尝试使用标准选项进行过滤(过滤器/排除/包含)
$files = Get-ChildItem -Path '~' -Recurse -file -Include *.txt -Exclude *anac*, *bz*
尽管不确定是内置过滤器选项还是运算符可以加快执行速度,但我认为它仍然会扫描所有文件。您可以尝试仅循环浏览文件夹(而不是递归搜索),并跳过那些文件夹以避免在其中扫描文件。