137

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.

How?

ΩmegaMan
  • 29,542
  • 12
  • 100
  • 122
culter
  • 5,487
  • 15
  • 54
  • 66

10 Answers10

204

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
Goyuix
  • 23,614
  • 14
  • 84
  • 128
  • 11
    For more useful methods in the System.IO.Path class without referring to MSDN documentation, you can use `[System.IO.Path] | Get-Member -Static` – Phil Feb 28 '13 at 20:03
  • 3
    Note that `[System.IO.Path]::GetExtension` returns the extension *including the period (".")*. – Ohad Schneider May 08 '16 at 13:15
28

just do it:

$file=Get-Item "C:\temp\file.htm"
$file.Basename 
$file.Extension
Esperento57
  • 16,521
  • 3
  • 39
  • 45
23
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
Community
  • 1
  • 1
Straff
  • 5,499
  • 4
  • 33
  • 31
15

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];
Ernest Correale
  • 451
  • 3
  • 5
14

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
CB.
  • 58,865
  • 9
  • 159
  • 159
11
PS C:\Users\joshua> $file = New-Object System.IO.FileInfo('file.type')
PS C:\Users\joshua> $file.BaseName, $file.Extension
file
.type
Jaqueline Vanek
  • 1,100
  • 10
  • 20
8

Check the BaseName and Extension properties of the FileInfo object.

Shay Levy
  • 121,444
  • 32
  • 184
  • 206
  • 1
    Any particular infoyou're after? Just pipe a file to Get-Member to reveal all of it;s members or browse to MSDN to find the official help. – Shay Levy Mar 13 '13 at 07:49
2

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.

Jacob Degeling
  • 358
  • 3
  • 12
1

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"))
john v kumpf
  • 431
  • 3
  • 8
0

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