【问题标题】:Removing path and extension from filename in PowerShell从 PowerShell 中的文件名中删除路径和扩展名
【发布时间】:2012-09-19 22:39:35
【问题描述】:

我有一系列字符串,它们是文件的完整路径。我想只保存文件名,没有文件扩展名和前导路径。所以从这里:

c:\temp\myfile.txt

myfile

我实际上并没有遍历目录,在这种情况下,可以使用类似 PowerShell 的 basename 属性的东西,但我只处理字符串。

【问题讨论】:

  • 许多答案没有考虑问题的第二部分。当使用 Get-Item、Get-ChildItem 或它们的别名 ls、dir、gi、gci 时,测试字符串中的文件必须存在。当我们检查一系列字符串而不是遍历目录时,必须假设这些文件不需要存在于运行该脚本的计算机上。

标签: powershell


【解决方案1】:

解决显示完整路径、目录、文件名或文件扩展名的问题比我想象的要容易。

                                           ## Output:
$PSCommandPath                             ## C:\Users\user\Documents\code\ps\test.ps1
(Get-Item $PSCommandPath ).Extension       ## .ps1
(Get-Item $PSCommandPath ).Basename        ## test
(Get-Item $PSCommandPath ).Name            ## test.ps1
(Get-Item $PSCommandPath ).DirectoryName   ## C:\Users\user\Documents\code\ps
(Get-Item $PSCommandPath ).FullName        ## C:\Users\user\Documents\code\ps\test.ps1

$ConfigINI = (Get-Item $PSCommandPath ).DirectoryName+"\"+(Get-Item $PSCommandPath ).BaseName+".ini"

$ConfigINI                                 ## C:\Users\user\Documents\code\ps\test.ini

其他形式:

$scriptPath = split-path -parent $MyInvocation.MyCommand.Definition
split-path -parent $PSCommandPath
Split-Path $script:MyInvocation.MyCommand.Path
split-path -parent $MyInvocation.MyCommand.Definition
[io.path]::GetFileNameWithoutExtension($MyInvocation.MyCommand.Name)

【讨论】:

  • 如果在顶部代码 sn-p 中的每个示例旁边您能准确地显示将返回的文本,那就太好了。
  • 我不知道 .csr 文件名但我知道文件存在的示例:$csr = Get-ChildItem -Path "$($domain.FullName)/*.csr" 然后Write-Host "fileName: $($csr.Basename)"
  • @Leonardo Get-Item 要求文件存在,否则会抛出错误
  • @SebMa $PSCommandPath 返回当前正在运行的脚本的信息,执行前应该处于保存状态。 Get-Item 在这种情况下应该总是返回一个有效值。
【解决方案2】:

有一个方便的 .NET 方法:

C:\PS> [io.path]::GetFileNameWithoutExtension("c:\temp\myfile.txt")
myfile

【讨论】:

  • 这个方法名有误导性……好像得到的文件名不带扩展名或文件路径。如果它是您想要的,那将很有用,但如果您只想删除扩展程序,则会破坏交易......找到这种方法的人会被引导相信。
  • 现在,在 PowerShell v7 上,我只需使用 Split-Path C:\temp\myfile.txt -LeafBase
  • @KeithHill 谢谢! -LeafBase 是在 powershell v6 中为其他好奇的人引入的
  • @TylerH 我没有发现这个方法名称具有误导性。相反,我发现它与 [io.path]::GetFileName 非常一致。我想说 GetFileName 的意图很明确,GetFileNameWithoutExtension 应该做同样的事情——没有扩展名。
【解决方案3】:

灵感来自@walid2mi 的answer

(Get-Item 'c:\temp\myfile.txt').Basename

请注意:这仅在给定文件确实存在时才有效。

【讨论】:

    【解决方案4】:

    @Keith,

    这里有另一种选择:

    PS II> $f="C:\Downloads\ReSharperSetup.7.0.97.60.msi"
    
    PS II> $f.split('\')[-1] -replace '\.\w+$'
    
    PS II> $f.Substring(0,$f.LastIndexOf('.')).split('\')[-1]
    

    【讨论】:

      【解决方案5】:

      从 PowerShell 6 开始,您将获得不带扩展名的文件名,如下所示:

      split-path c:\temp\myfile.txt -leafBase
      

      【讨论】:

      • 这在 powershell 6 中是正确的。在 bog 标准 5.1 中没有 LeafBase
      • 感谢您的信息,我已相应地更新了答案。什么是沼泽
      • 道歉 :) 我来自(英国),“沼泽标准”是一个俚语,指完全普通的东西,一个“香草”版本。
      【解决方案6】:

      ([io.fileinfo]"c:\temp\myfile.txt").basename
      

      "c:\temp\myfile.txt".split('\.')[-2]
      

      【讨论】:

      • 第二个例子不能很好地与类似 - "C:\Downloads\ReSharperSetup.7.0.97.60.msi".split('\.')[-2]
      • @KeithHill 专业文件名除了我收集的扩展名的点之外没有点。但这有待商榷。如果一个慷慨,一个会假设扩展三个字符,所以我会$FileNameWoExt = $FileName.Substring(0, $FileName.Length -4)
      • “假设三个字符的扩展”不是一个好的假设。有很多扩展使用多于或少于三个字符,例如:.psd1、.psm1、.json、.docx、.xslx、.pptx、.appx、.appbundle、.cs、.fs、.c、.h , .py 等
      【解决方案7】:

      这是一个没有括号的

      [io.fileinfo] 'c:\temp\myfile.txt' | % basename
      

      【讨论】:

        【解决方案8】:

        这里有几个 PowerShell 5.1 单行选项,它们将路径放在行首。

        'c:\temp\myfile.txt' |%{[io.fileinfo]$_ |% basename}
        

        "c:\temp\myfile.txt" | Split-Path -Leaf | %{$_ -replace '\.\w+$'}
        

        【讨论】:

          【解决方案9】:

          你可以使用 basename 属性

          PS II> ls *.ps1 | select basename
          

          【讨论】:

          • OP 说:我实际上并没有遍历目录。
          【解决方案10】:

          扩展 René Nyffenegger 的回答,对于那些无法访问 PowerShell 版本 6.x 的人,我们使用不测试文件存在的拆分路径:

          Split-Path "C:\Folder\SubFolder\myfile.txt" -Leaf
          

          这将返回“myfile.txt”。如果我们知道文件名中没有句点,我们可以拆分字符串并取第一部分:

          (Split-Path "C:\Folder\SubFolder\myfile.txt" -Leaf).Split('.') | Select -First 1
          

          (Split-Path "C:\Folder\SubFolder\myfile.txt" -Leaf).Split('.')[0]
          

          这将返回“myfile”。 如果文件名可能包含句点,为了安全起见,我们可以使用以下内容:

          $FileName = Split-Path "C:\Folder\SubFolder\myfile.txt.config.txt" -Leaf
          $Extension = $FileName.Split('.') | Select -Last 1
          $FileNameWoExt = $FileName.Substring(0, $FileName.Length - $Extension.Length - 1)
          

          这将返回“myfile.txt.config”。 在这里,我更喜欢使用 Substring() 而不是 Replace(),因为前面有句点的扩展名也可以是名称的一部分,如我的示例所示。通过使用 Substring,我们根据请求返回不带扩展名的文件名。

          【讨论】:

            【解决方案11】:

            下面的命令会将文件夹中的所有文件存储在一个变量中,匹配扩展名“.txt”:

            $allfiles=Get-ChildItem -Path C:\temp\*" -Include *.txt
            foreach ($file in $allfiles) {
                Write-Host $file
                Write-Host $file.name
                Write-Host $file.basename
            }
            

            $file 给出文件的路径、名称和扩展名:c:\temp\myfile.txt

            $file.name 给出文件名和扩展名:myfile.txt

            $file.basename 只给出文件名:myfile

            【讨论】:

            • 好的,但问题是关于文件名(字符串),而不是实际文件。
            【解决方案12】:

            此脚本在文件夹和子文件夹中搜索并通过删除扩展名来重命名文件

                Get-ChildItem -Path "C:/" -Recurse -Filter *.wctc |
            
                Foreach-Object {
            
                  rename-item $_.fullname -newname $_.basename
            
                }
            

            【讨论】:

              【解决方案13】:

              这可以通过多次拆分字符串来完成。

              #Path
              $Link = "http://some.url/some/path/file.name"
              
              #Split path on "/"
              #Results of split will look like this : 
              # http:
              #
              # some.url
              # some
              # path
              # file.name
              $Split = $Link.Split("/")
              
              #Count how many Split strings there are
              #There are 6 strings that have been split in my example
              $SplitCount = $Split.Count
              
              #Select the last string
              #Result of this selection : 
              # file.name
              $FilenameWithExtension = $Split[$SplitCount -1]
              
              #Split filename on "."
              #Result of this split : 
              # file
              # name
              $FilenameWithExtensionSplit = $FilenameWithExtension.Split(".")
              
              #Select the first half
              #Result of this selection : 
              # file
              $FilenameWithoutExtension = $FilenameWithExtensionSplit[0]
              
              #The filename without extension is in this variable now
              # file
              $FilenameWithoutExtension
              

              这里是没有 cmets 的代码:

              $Link = "http://some.url/some/path/file.name"
              $Split = $Link.Split("/")
              $SplitCount = $Split.Count
              $FilenameWithExtension = $Split[$SplitCount -1]
              $FilenameWithExtensionSplit = $FilenameWithExtension.Split(".")
              $FilenameWithoutExtension = $FilenameWithExtensionSplit[0]
              $FilenameWithoutExtension
              

              【讨论】:

              • 为什么这么难?
              • 如果文件名包含多个句点则不起作用,例如MyApp.exe.config
              【解决方案14】:

              给定任意路径字符串,System.IO.Path 对象上的各种静态方法给出以下结果。

              strTestPath = C:\Users\DAG\Documents\Articles_2018\NTFS_File_Times_in_CMD\PathStringInfo.ps1 GetDirectoryName = C:\Users\DAG\Documents\Articles_2018\NTFS_File_Times_in_CMD GetFileName = PathStringInfo.ps1 获取扩展 = .ps1 GetFileNameWithoutExtension = PathStringInfo

              以下是生成上述输出的代码。

              [console]::Writeline( "strTestPath                 = {0}{1}" ,
                                    $strTestPath , [Environment]::NewLine );
              [console]::Writeline( "GetDirectoryName            = {0}" ,
                                    [IO.Path]::GetDirectoryName( $strTestPath ) );
              [console]::Writeline( "GetFileName                 = {0}" ,
                                    [IO.Path]::GetFileName( $strTestPath ) );
              [console]::Writeline( "GetExtension                = {0}" ,
                                    [IO.Path]::GetExtension( $strTestPath ) );
              [console]::Writeline( "GetFileNameWithoutExtension = {0}" ,
                                    [IO.Path]::GetFileNameWithoutExtension( $strTestPath ) );
              

              编写和测试生成上述内容的脚本发现了一些关于 PowerShell 与 C#、C、C++、Windows NT 命令脚本语言以及几乎所有其他我有经验的东西的不同之处。

              【讨论】:

                猜你喜欢
                • 2011-04-09
                • 1970-01-01
                • 2012-06-29
                • 1970-01-01
                • 2019-12-01
                • 1970-01-01
                • 2013-02-10
                • 2015-04-19
                • 1970-01-01
                相关资源
                最近更新 更多