131
votes

I have a series of strings which are full paths to files. I'd like to save just the filename, without the file extension and the leading path. So from this:

c:\temp\myfile.txt

to

myfile

I'm not actually iterating through a directory, in which case something like PowerShell's basename property could be used, but rather I'm dealing with strings alone.

14
many answers are not taking in account second part of the question. When Get-Item, Get-ChildItem, or their aliases ls, dir, gi, gci are used, the file from the tested string must exist. When we are checking a series of string and not iterating through a directory, it must be assumed those files doesn't need to exist on computer where this script will be run.papo

14 Answers

131
votes

There's a handy .NET method for that:

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

Way easier than I thought to address the issue of displaying the full path, directory, file name or file extension.

$PSCommandPath
(Get-Item $PSCommandPath ).Extension
(Get-Item $PSCommandPath ).Basename
(Get-Item $PSCommandPath ).Name
(Get-Item $PSCommandPath ).DirectoryName
(Get-Item $PSCommandPath ).FullName
$ConfigINI = (Get-Item $PSCommandPath ).DirectoryName+"\"+(Get-Item $PSCommandPath ).BaseName+".ini"
$ConfigINI

other forms:

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

Inspired by an answer of @walid2mi:

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

Please note: this only works if the given file really exists.

30
votes

or

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

or

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

you can use basename property

PS II> ls *.ps1 | select basename
10
votes

Starting with PowerShell 6, you get the filename without extension like so:

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

@Keith,

here another option:

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]
5
votes

Expanding on René Nyffenegger's answer, for those who do not have access to PowerShell version 6.x, we use Split Path, which doesn't test for file existence:

Split-Path "C:\Folder\SubFolder\myfile.txt" -Leaf

This returns "myfile.txt". If we know that the file name doesn't have periods in it, we can split the string and take the first part:

(Split-Path "C:\Folder\SubFolder\myfile.txt" -Leaf).Split('.') | Select -First 1

or

(Split-Path "C:\Folder\SubFolder\myfile.txt" -Leaf).Split('.')[0]

This returns "myfile". If the file name might include periods, to be safe, we could use the following:

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

This returns "myfile.txt.config". Here I prefer to use Substring() instead of Replace() because the extension preceded by a period could also be part of the name, as in my example. By using Substring we return the filename without the extension as requested.

4
votes

Given any arbitrary path string, various static methods on the System.IO.Path object give the following results.

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

Following is the code that generated the above output.

[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 ) );

Writing and testing the script that generated the above uncovered some quirks about how PowerShell differs from C#, C, C++, the Windows NT command scripting language, and just about everything else with which I have any experience.

3
votes

This script searches in a folder and sub folders and rename files by removing their extension

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

    Foreach-Object {

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

    }
2
votes

This can be done by splitting the string a couple of times.

#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

Here is the code without comments :

$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
1
votes

Here is one without parentheses

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

The command below will store in a variable all the file in your folder, matchting the extension ".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 gives the file with path, name and extension: c:\temp\myfile.txt

$file.name gives file name & extension: myfile.txt

$file.basename gives only filename: myfile

0
votes

Here are a couple PowerShell 5.1 one-liner options that put the path at the start of the line.

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

OR

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