powershell - extract file name and extension
Sebastian Wright
I need to extract file name and extension from e.g. my.file.xlsx. I don't know the name of file or extension and there may be more dots in the name, so I need to search the string from the right and when I find first dot (or last from the left), extract the part on the right side and the part on the left side from that dot.
Maybe there is better solution, but I did'n find anything here or anywhere else. Thank you
010 Answers
If the file is coming off the disk and as others have stated, use the BaseName and Extension properties:
PS C:\> dir *.xlsx | select BaseName,Extension
BaseName Extension
-------- ---------
StackOverflow.com Test Config .xlsx If you are given the file name as part of string (say coming from a text file), I would use the GetFileNameWithoutExtension and GetExtension static methods from the System.IO.Path class:
PS C:\> [System.IO.Path]::GetFileNameWithoutExtension("Test Config.xlsx")
Test Config
PS H:\> [System.IO.Path]::GetExtension("Test Config.xlsx")
.xlsx 2 PS C:\Windows\System32\WindowsPowerShell\v1.0>split-path "H:\Documents\devops\tp-mkt-SPD-38.4.10.msi" -leaf
tp-mkt-SPD-38.4.10.msi
PS C:\Windows\System32\WindowsPowerShell\v1.0> $psversiontable
Name Value
---- -----
CLRVersion 2.0.50727.5477
BuildVersion 6.1.7601.17514
PSVersion 2.0
WSManStackVersion 2.0
PSCompatibleVersions {1.0, 2.0}
SerializationVersion 1.1.0.1
PSRemotingProtocolVersion 2.1 1 just do it:
$file=Get-Item "C:\temp\file.htm"
$file.Basename
$file.Extension 2 If is from a text file and and presuming name file are surrounded by white spaces this is a way:
$a = get-content c:\myfile.txt
$b = $a | select-string -pattern "\s.+\..{3,4}\s" | select -ExpandProperty matches | select -ExpandProperty value
$b | % {"File name:{0} - Extension:{1}" -f $_.substring(0, $_.lastindexof('.')) , $_.substring($_.lastindexof('.'), ($_.length - $_.lastindexof('.'))) }If is a file you can use something like this based on your needs:
$a = dir .\my.file.xlsx # or $a = get-item c:\my.file.xlsx
$a Directory: Microsoft.PowerShell.Core\FileSystem::C:\ps
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 25/01/10 11.51 624 my.file.xlsx
$a.BaseName
my.file
$a.Extension
.xlsx Use Split-Path
$filePath = "C:\PS\Test.Documents\myTestFile.txt";
$fileName = (Split-Path -Path $filePath -Leaf).Split(".")[0];
$extension = (Split-Path -Path $filePath -Leaf).Split(".")[1]; 3 PS C:\Users\joshua> $file = New-Object System.IO.FileInfo('file.type')
PS C:\Users\joshua> $file.BaseName, $file.Extension
file
.type Check the BaseName and Extension properties of the FileInfo object.
1As of PowerShell 6.0, Split-Path has an -Extenstion parameter. This means you can do:
$path | Split-Path -Extensionor
Split-Path -Path $path -ExtensionFor $path = "test.txt" both versions will return .txt, inluding the full stop.
This is an adaptation, if anyone is curious. I needed to test whether RoboCopy successfully copied one file to multiple servers for its integrity:
$Comp = get-content c:\myfile.txt
ForEach ($PC in $Comp) { dir "\\$PC\Folder\Share\*.*" | Select-Object $_.BaseName
}Nice and simple, and it shows the directory and the file inside it. If you want to specify one file name or extension, just replace the *'s with whatever you want.
Directory: \\SERVER\Folder\Share
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 2/27/2015 5:33 PM 1458935 Test.pptx if [System.IO.Path]::GetFileNameWithoutExtension() is hard to type or remember:
("file.name.ext.w..dots.ext" -split '\.' | select -SkipLast 1) -join '.'
# >> file.name.ext.w..dots
"file.name.ext.w..dots.ext" -split '\.' | select -Last 1
# >> extNotes:
-split takes a regex (by default) so the . has to be escaped
I don't think there's a "locale" name.ext filename separator, is there?
-SkipLast was added in v5.0
The .NET function [System.IO.Path]::GetExtension() returns the extension including the '.' char; the above returns it without
having to -rejoin the string after splitting could change the result, I suppose, in unusual circumstances. Or if you're uncomfortable re-joining a string that's already joined, one could:
$file = "file.name.ext.w..dots.ext"
$ext = $file -split '\.' | select -Last 1
$name = $file.Substring(0, $file.LastIndexOf(".$ext"))