Rimozione di percorso ed estensione dal nome del file in PowerShell


99

Ho una serie di stringhe che sono percorsi completi ai file. Vorrei salvare solo il nome del file, senza l'estensione del file e il percorso iniziale. Quindi da questo:

c:\temp\myfile.txt

per

myfile

In realtà non sto iterando attraverso una directory, nel qual caso basenamepotrebbe essere usata qualcosa come la proprietà di PowerShell , ma piuttosto ho a che fare con le stringhe.


7
molte risposte non tengono conto della seconda parte della domanda. Quando vengono utilizzati Get-Item, Get-ChildItem o i loro alias ls, dir, gi, gci, il file dalla stringa testata deve esistere . Quando controlliamo una serie di stringhe e non iteriamo in una directory , si deve presumere che quei file non debbano esistere sul computer in cui verrà eseguito questo script.
papo

Risposte:


110

C'è un pratico metodo .NET per questo:

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

93

È molto più semplice di quanto pensassi affrontare il problema della visualizzazione del percorso completo, della directory, del nome del file o dell'estensione del file.

$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

altre forme:

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

25
Sarebbe bello se accanto a ogni esempio nello snippet di codice in alto mostrassi esattamente quale testo verrebbe restituito.
Deadlydog

Esempio in cui non conosco il nome del file .csr, ma so che esiste un file: $csr = Get-ChildItem -Path "$($domain.FullName)/*.csr"alloraWrite-Host "fileName: $($csr.Basename)"
Scott Pelak

46

Ispirato da una risposta di @ walid2mi:

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

Nota: funziona solo se il file specificato esiste davvero .


1
Questo è il modo più semplice per ottenere il nome del file per un singolo file.
Marisks

6
Ciò presuppone che il file esista. La rimozione di un'estensione da un nome di file non dovrebbe dipendere da questo. Cosa succede se stai creando un file basato su un nome file in cui il file non esiste? Il percorso è una stringa e deve essere trattato come una stringa, non si presume che sia un file esistente.
Antony Booth

29

o

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

o

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

9
Il secondo esempio non funziona molto bene con qualcosa come - "C: \ Downloads \ ReSharperSetup.7.0.97.60.msi" .split ('\.') [- 2]
Keith Hill,

24

puoi usare la proprietà basename

PS II> ls *.ps1 | select basename

7
L'OP dice: in realtà non sto iterando attraverso una directory.
CB.

1
Molto utile per me!
iheartcsharp

5

@Keith ,

ecco un'altra opzione:

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]

4

Data una stringa di percorso arbitraria, vari metodi statici sull'oggetto System.IO.Path forniscono i seguenti risultati.

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

Di seguito è riportato il codice che ha generato l'output di cui sopra.

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

Scrivere e testare lo script che ha generato quanto sopra ha scoperto alcune stranezze su come PowerShell differisce da C #, C, C ++, il linguaggio di scripting dei comandi di Windows NT e quasi tutto il resto con cui ho esperienza.


3

A partire da PowerShell 6, ottieni il nome del file senza estensione in questo modo:

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

Questo è corretto in PowerShell 6. Non c'è LeafBase in bog standard 5.1
finlaybob

1
Grazie per le informazioni, ho aggiornato la risposta di conseguenza. Cos'è la palude ?
René Nyffenegger

2
Mi scuso :) da dove vengo (Regno Unito), "Bog Standard" è un termine gergale per qualcosa di completamente ordinario, una versione "vaniglia".
finlaybob

2

Questo script cerca in una cartella e sottocartelle e rinomina i file rimuovendone l'estensione

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

    Foreach-Object {

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

    }

2

Espandendo la risposta di René Nyffenegger, per coloro che non hanno accesso a PowerShell versione 6.x, utilizziamo Split Path, che non verifica l'esistenza del file:

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

Ciò restituisce " myfile.txt ". Se sappiamo che il nome del file non contiene punti, possiamo dividere la stringa e prendere la prima parte:

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

o

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

Ciò restituisce " myfile ". Se il nome del file potrebbe includere punti, per sicurezza, potremmo utilizzare quanto segue:

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

Ciò restituisce " myfile.txt.config ". Qui preferisco usare Substring () invece di Replace () perché l'estensione preceduta da un punto potrebbe anche far parte del nome, come nel mio esempio. Utilizzando Substring restituiamo il nome del file senza l'estensione come richiesto.


1
grazie mille per questa risposta, è molto completa e mi ha aiutato
Sam

1

Eccone uno senza parentesi

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

1

Questo può essere fatto dividendo la stringa un paio di volte.

#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

Ecco il codice senza commenti:

$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
Perché così difficile?
Jaroslav Štreit

2
Non funziona se il nome del file contiene più di un punto, ad esempio MyApp.exe.config
Joe
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.