【问题标题】:Check if a path is a folder or a file in PowerShell检查路径是PowerShell中的文件夹还是文件
【发布时间】:2017-02-11 00:49:12
【问题描述】:

我正在尝试编写一个 PowerShell 脚本,该脚本遍历文件夹或文件路径的值列表,并首先删除文件,然后删除空文件夹。

到目前为止我的脚本:

[xml]$XmlDocument = Get-Content -Path h:\List_Files.resp.xml
$Files =  XmlDocument.OUTPUT.databrowse_BrowseResponse.browseResult.dataResultSet.Path

现在我正在尝试测试变量中的每一行以查看它是否是一个文件并首先将其删除,然后检查并删除子文件夹和文件夹。这只是为了让它成为一个干净的过程。

我不能完全让这个下一点工作,但我想我需要这样的东西:

foreach ($file in $Files)
{
    if (! $_.PSIsContainer)
    {
        Remove-Item $_.FullName}
    }
}

下一节可以清理子文件夹和文件夹。

有什么建议吗?

【问题讨论】:

  • 在循环中使用 $file 而不是 $_。

标签: powershell


【解决方案1】:

我找到了解决这个问题的方法:使用Test-Path cmdlet 和参数-FileType 等于Leaf 来检查它是否是一个文件或Container 来检查它是否是一个文件夹:

# Check if file (works with files with and without extension)
Test-Path -Path 'C:\Demo\FileWithExtension.txt' -PathType Leaf
Test-Path -Path 'C:\Demo\FileWithoutExtension' -PathType Leaf

# Check if folder
Test-Path -Path 'C:\Demo' -PathType Container

我最初找到了解决方案here。而官方参考是here

【讨论】:

  • 这完全是一个灾难的答案,“Container”和“Leaf”担心regkeys不是目录或文件!!!
  • 因为@muhammad-murad-haider sai 唯一正确的方法是(get-item "C:\somefolder").PSIsContainer
【解决方案2】:

我认为您的 $Files 对象是一个字符串数组:

PS D:\PShell> $Files | ForEach-Object {"{0} {1}" -f $_.Gettype(), $_}
System.String D:\PShell\SO
System.String D:\PShell\SU
System.String D:\PShell\test with spaces
System.String D:\PShell\tests
System.String D:\PShell\addF7.ps1
System.String D:\PShell\cliparser.ps1

不幸的是,PSIsContainer 属性不能在 string 对象上找到,而是在 filesystem 对象上,例如

PS D:\PShell> Get-ChildItem | ForEach-Object {"{0} {1}" -f $_.Gettype(), $_}
System.IO.DirectoryInfo SO
System.IO.DirectoryInfo SU
System.IO.DirectoryInfo test with spaces
System.IO.DirectoryInfo tests
System.IO.FileInfo addF7.ps1
System.IO.FileInfo cliparser.ps1

从字符串中获取文件系统对象:

PS D:\PShell> $Files | ForEach-Object {"{0} {1}" -f (Get-Item $_).Gettype(), $_}
System.IO.DirectoryInfo D:\PShell\SO
System.IO.DirectoryInfo D:\PShell\SU
System.IO.DirectoryInfo D:\PShell\test with spaces
System.IO.DirectoryInfo D:\PShell\tests
System.IO.FileInfo D:\PShell\addF7.ps1
System.IO.FileInfo D:\PShell\cliparser.ps1

尝试下一个代码 sn-p:

$Files | ForEach-Object 
  {
    $file = Get-Item $_               ### string to a filesystem object
    if ( -not $file.PSIsContainer)
        {
            Remove-Item $file}
        }
  }

【讨论】:

    【解决方案3】:

    我们可以使用get-item 命令并提供路径。然后您可以检查PSIsContainer(布尔值)属性,该属性将确定提供的路径是针对文件夹还是文件。例如

    $target = get-item "C:\somefolder" # or "C:\somefolder\somefile.txt"
    if($target.PSIsContainer) {
    # it's a folder
    }
    else { #its a file }
    

    希望这对未来的访客有所帮助。

    【讨论】:

      【解决方案4】:

      考虑以下代码:

      $Files = Get-ChildItem -Path $env:Temp
      
      foreach ($file in $Files)
      {
          $_.FullName
      }
      
      $Files | ForEach {
          $_.FullName
      }
      

      第一个 foreach 是用于循环的 PowerShell 语言命令,第二个 ForEach 是 ForEach-Object cmdlet 的别名,这是完全不同的。

      ForEach-Object 中,$_ 指向循环中的当前对象,从$Files 集合通过管道输入,但在第一个foreach 中,$_ 没有任何意义。

      在foreach循环中使用循环变量$file

      foreach ($file in $Files)
      {
          $file.FullName
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-03-15
        • 1970-01-01
        • 2018-12-18
        • 1970-01-01
        • 2012-09-28
        • 1970-01-01
        • 2018-05-23
        • 1970-01-01
        相关资源
        最近更新 更多