脚本返回错误:“Get-Content : 指定路径上的对象 ... 不存在,或已被 -Include 或 -Exclude 参数过滤

问题描述

编辑 我想我现在知道问题是什么 - 副本号并不是文件名的真正组成部分。因此,当数组拉取它然后用于获取匹配信息时,数组中的文件不存在,只有文件名没有副本号。

我尝试编写重命名脚本,但存在同样的问题...只有我手动重命名的少数文件(因此它们不包含副本号)被脚本重命名(成功)。所有其他人都显示不存在。

我该如何解决这个问题?我真的不想手动处理 23000 多个文件。我在画一个空白..

请帮助


我正在尝试根据内容缩小包含同名“SCADA Alert.eml”、“SCADA Alert[1].eml”...[23110] 电子邮件(副本)的文件夹。并从文件夹中删除符合特定内容标准的电子邮件

当我运行它时,我不断收到上面主题行中的错误。它只看到第一个文件,其余的它说不存在......

脚本读取文件夹,创建名称数组(正确执行此操作)。 然后创建一个变量 $email,并分配该文件内容。对于数组中的每个 $filename。 (这是休息的地方)

然后应该将我要查找的特定字符串与 $email var 的内容匹配并返回 true 或 false。如果为真,我希望它从文件夹中删除电子邮件 $filename。

因此缩小了我必须查看的电子邮件范围。 非常感谢这里的任何帮助。

这是我目前所拥有的...(文件夹在 C 的根目录中:)

$array = Get-ChildItem -name -Path $FolderToRead   #| Get-Content | Tee C:\Users\baudet\desktop\TargetFile.txt

Foreach ($FileName in $array){

    $FileName          # Check File

    $email = Get-Content $FolderToRead\$FileName  
    $email             # Check Content

    $Containsstring = "False"                      # Set Var 
    $Containsstring                                # Verify Var
    $Containsstring = %{$email -match "SYS$,ROC"}  # Look for String
    $Containsstring                                # Verify result of match

        #if ($Containsstring -eq "True") {
            #Remove-Item $FolderToRead\$element
            #}
}

解决方法

这里有一个 PowerShell 惯用的解决方案,它也可以解决您的原始问题:

Get-ChildItem -File -LiteralPath $FolderToRead | Where-Object {
  (Get-Content -Raw -LiteralPath $_.FullName) -match 'SYS\$,ROC'
} | Remove-Item -WhatIf

注意:上面命令中的-WhatIf common parameter预览操作。一旦您确定操作会满足您的要求,请移除 -WhatIf

注意 -match 运算符的 RHS regex 中的 $ 字符是如何被 \ 转义的,以便逐字 em>(而不是元字符 $,输入结束锚点)。

此外,鉴于 $ 也用于 PowerShell 的字符串插值,最好使用 '...' 字符串(-quoted,verbatim字符串)来表示正则表达式,假设在正则表达式引擎看到结果字符串之前不需要实际的前置字符串扩展 - 有关详细信息,请参阅 this answer


至于你尝试了什么

  • 错误消息源于这样一个事实,即 Get-Content $FolderToRead\$FileName 将文件名参数 $FolderToRead\$FileName 隐式(位置)绑定到 Get-Content-Path 参数,它期望 PowerShell wildcard patterns

    • 由于您的文件名字面上包含 [] 字符,它们会被(隐含的)-Path 参数误解可以通过使用 -LiteralPath 参数来避免(必须明确指定,作为 named 参数)。
  • %{$email -match "SYS$,ROC"} 不必要地包含在 ForEach-Object 调用中(% 是内置别名);虽然在这种情况下这不会造成任何伤害,但会增加不必要的开销;
    $email -match "SYS$,ROC" 就够了,不过还需要修正为
    $email -match 'SYS\$,ROC',如上所述。

,
[System.IO.Directory]::EnumerateFiles($Folder) |
    Where-Object {$true -eq [System.IO.File]::ReadAllText($_,[System.Text.Encoding]::UTF8).Contains('SYS$,ROC') } |
    ForEach-Object {
        Write-Host "Removing $($_)"
        #[System.IO.File]::Delete($_)
    }

你的错误:

  1. %{$email -match "SYS$,ROC"} - % 是什么意思?这是 ForEach-Object 别名。
  2. %{$email -match "SYS$,ROC"} - 为什么使用 -match?这比 -likeString.Contains()
  3. 慢得多
  4. %{$email -match "SYS$,ROC"} - 在双引号内使用 $ 时,您应该使用单反引号符号 (I have `$100) 对其进行转义。否则,$ 之后的所有内容都是变量名:Hello,$username; I's $($weather.ToString()) today!
  5. 以正确的方式编写调试输出:使用 Write-DebugWrite-VerboseWrite-HostWrite-WarningWrite-ErrorWrite-Information。立>

可以更好:

  1. 避免使用 Get-ChildItem,因为 Get-ChildItem 返回带有属性(如 mtime、atime、ctime 等)的文件。此附加信息是每个文件的附加请求。当您只需要文件列表时,请使用来自 EnumerateFiles 的原生 .Net System.IO.Directory。这是在处理大量文件时的显着性能提升。
  2. 使用 RealAllText 静态类中的 ReadAllLinesReadAllBytesSystem.IO.File 更具体,而不是使用 universal Get-Content。立>
  3. 使用管道;-)