【问题标题】:Powershell - Find out if there are two files with the same namePowershell - 找出是否有两个同名文件
【发布时间】:2014-07-29 18:02:26
【问题描述】:

我正在尝试检查一系列目录和子目录,以查看同一个文件夹中是否有两个或多个同名文件。我认为我的问题是我如何尝试验证字符串。

对于以下测试目录:

  • |-- C:\测试\
    • |--C:\Test\YY\
      • |--C:\Test\YY\xx.log
      • |--C:\Test\YY\xx.txt
    • |-- C:\Test\ZZ\
    • |-- C:\Test\ZZ.log
    • |-- C:\Test\ZZ.txt

我需要我的代码来查找 xx.log 和 ZZ.log。我可以对$_.PSisContainer 进行检查(但我认为没有必要)。

ForEach ($item in (gci "C:\Test\*" -recurse)) {
    If ($item.extension -notmatch "txt" -AND $item.basename+".txt" -eq $True) {
        Write-Host $item.fullname
        } 
    }

$item.basename+".txt" 提供了正确的字符串,但我无法使用该字符串来验证文件是否存在。

谁能帮助纠正我的代码?我想学习如何处理这样的连接字符串——我认为这是一个在其他领域有用的技巧。

【问题讨论】:

    标签: powershell get-childitem file-comparison


    【解决方案1】:

    这不是一个答案,而是一个评论,但是现在不允许我添加 cmets :(

    R_C_III - 我猜原始代码中有两个错误。

    首先,它不会构建完整的文件路径(即 DirectoryName + BaseName + .TXT)。 Keith 没有连接字符串来执行此操作,而是使用 PowerShell 在双引号字符串中执行值替换的能力。例如

    $s = "there"
    write-host "hello $s"
    

    结果

    hello there
    

    要以这种方式将对象属性插入字符串,必须使用 Keith 解释的子表达式。

    $file = get-item "c:\somefile.txt"
    write-host "$($file.DirectoryName)\$($file.BaseName).NEW"
    

    结果

    c:\somefile.NEW
    

    其次(根据我对基思回答的评论),原始代码不会检查文件的“.txt”版本是否存在。 IF 语句中的第二个子句尝试将修改后的文件名等同于 $True ($item.basename+".txt" -eq $True)。该子句将始终评估为假。

    Keith 的修改添加了“Test-Path”CmdLet,在本例中,它检查“.txt”文件是否存在。

    【讨论】:

    • 谢谢!很好的答案!我缩小了核心问题的范围:你能解释一下下面的例子吗? $item.basename+".txt" 产生 ZZ.txt 的 System.String test-path $item.basename+".txt" 找不到接受参数“+.txt”的位置参数错误,write-host $item.basename+".txt" 产生 ZZ +.txt $($item.basename+".txt") 产生 ZZ 的 System.String。 txt 和 write-host 显示 ZZ.txt 从外部看,这些应该是相同的,但 write-host 显示不同。我认为这是我在 OP 中的问题。不是所有的字符串都是平等的吗? @andyb @keith-hill
    • 强烈怀疑这与 PowerShell 解析模式有关。我向您推荐 Keith 的一篇优秀文章 (rkeithhill.wordpress.com/2007/11/24/…) 以及“get-help about_parsing”
    【解决方案2】:

    试试这个:

    gci C:\Test -recurse -file | Where {$_.extension -ne ".txt" -AND (Test-Path "$($_.DirectoryName)\$($_.BaseName).txt")}
    

    您不需要初始 Foreach 语句,因为可以在管道开始处直接使用输出数据的 PowerShell 命令。然后使用Where 命令过滤管道对象。

    【讨论】:

    • 效果很好!谢谢!你能解释一下“$($_.DirectoryName)\$($_.BaseName).txt”是如何工作的吗? $() 如何做我的 $_.Basename+".txt" 没有做的事情?
    • 要在字符串中计算表达式,例如属性引用,您需要使用子表达式,即$()
    • R_C_III - 在我看来,您的原始表达式正在尝试将字符串 ($item.basename+".txt") 和布尔值 ($True) 等同起来。 Keith 添加了用于检查文件是否存在的 Test-Path CmdLet。
    猜你喜欢
    • 1970-01-01
    • 2018-02-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-17
    • 1970-01-01
    • 1970-01-01
    • 2022-11-02
    • 1970-01-01
    相关资源
    最近更新 更多