Powershell - Extract File Name and Extension
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...
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
10 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
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
just do it:
$file=Get-Item "C:\temp\file.htm"
$file.Basename
$file.Extension
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];
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.
As of PowerShell 6.0, Split-Path has an -Extenstion parameter. This means you can do:
$path | Split-Path -Extension
or
Split-Path -Path $path -Extension
For $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
# >> ext
Notes:
-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"))