在 PowerShell 中删除文件名中的路径和扩展名

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

c:\temp\myfile.txt

myfile

我实际上并没有遍历一个目录,在这种情况下可以使用 PowerShell 的 basename属性,而是仅仅处理字符串。

240498 次浏览

有一个方便的.NET 方法:

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

可以使用 名字属性

PS II> ls *.ps1 | select basename

或者

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

或者

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

@ 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]

受@walid2mi 的 回答启发:

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

请注意: 只有当给定文件 真的存在时才能正常工作。

这里有一个没有括号的

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

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

                                           ## 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)

给定任意的路径字符串,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
GetExtension                = .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 命令脚本语言以及其他我有经验的所有东西的不同之处。

这可以通过分割字符串几次来完成。

#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

下面是没有注释的代码:

$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

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

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

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

    Get-ChildItem -Path "C:/" -Recurse -Filter *.wctc |


Foreach-Object {


rename-item $_.fullname -newname $_.basename


}

在 René Nyffenegger 的回答的基础上,对于那些没有使用 PowerShell 6.x 版本的用户,我们使用 Split Path,它不测试文件是否存在:

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]

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

$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)

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

下面的命令将在一个变量中存储文件夹中的所有文件,匹配扩展名“ . 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

这里有几个 PowerShell 5.1一行程序选项,它们将路径放在行的开头。

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

或者

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