Velvet Star Monitor

Standout celebrity highlights with iconic style.

updates

powershell - extract file name and extension

Writer 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

0

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
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.

1

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

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy