Usuwanie ścieżki i rozszerzenia z nazwy pliku w programie PowerShell


99

Mam serię ciągów, które są pełnymi ścieżkami do plików. Chciałbym zapisać samą nazwę pliku, bez rozszerzenia i wiodącej ścieżki. Więc z tego:

c:\temp\myfile.txt

do

myfile

Właściwie nie przechodzę przez katalog, w którym to przypadku basenamemożna użyć czegoś takiego jak właściwość PowerShell , ale raczej mam do czynienia z samymi ciągami.


7
wiele odpowiedzi nie uwzględnia drugiej części pytania. Gdy używane są Get-Item, Get-ChildItem lub ich aliasy ls, dir, gi, gci, plik z testowanego ciągu musi istnieć . Kiedy sprawdzamy serię ciągów i nie przechodzimy przez katalog , należy założyć, że te pliki nie muszą istnieć na komputerze, na którym ten skrypt zostanie uruchomiony.
papo

Odpowiedzi:


110

Jest do tego przydatna metoda .NET:

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

93

O wiele łatwiej niż myślałem, aby rozwiązać problem wyświetlania pełnej ścieżki, katalogu, nazwy pliku lub rozszerzenia pliku.

$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

inne formy:

$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
Byłoby miło, gdybyś obok każdego przykładu w górnym fragmencie kodu pokazał dokładnie, jaki tekst zostanie zwrócony.
śmiertelny pies

Przykład, w którym nie znam nazwy pliku .csr, ale wiem, że plik istnieje: $csr = Get-ChildItem -Path "$($domain.FullName)/*.csr"wtedyWrite-Host "fileName: $($csr.Basename)"
Scott Pelak

46

Zainspirowany odpowiedzią @ walid2mi:

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

Uwaga: działa to tylko wtedy, gdy dany plik naprawdę istnieje .


1
To najłatwiejszy sposób uzyskania nazwy pliku dla pojedynczego pliku.
marisks

6
Zakłada się, że plik istnieje. Usunięcie rozszerzenia z nazwy pliku nie powinno od tego zależeć. Co się stanie, jeśli tworzysz plik na podstawie nazwy pliku, którego nie ma? Ścieżka jest łańcuchem i powinna być traktowana jako ciąg znaków, a nie jako istniejący plik.
Antony Booth,

29

lub

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

lub

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

9
Drugi przykład nie działa zbyt dobrze z czymś takim jak - „C: \ Downloads \ ReSharperSetup.7.0.97.60.msi” .split ('\.') [- 2]
Keith Hill

24

możesz użyć właściwości basename

PS II> ls *.ps1 | select basename

7
OP mówi: tak naprawdę nie przechodzę przez katalog.
CB.

1
Bardzo przydatne dla mnie!
iheartcsharp

5

@Keith ,

tutaj inna opcja:

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

Biorąc pod uwagę dowolny ciąg ścieżki, różne metody statyczne obiektu System.IO.Path dają następujące wyniki.

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

Poniżej znajduje się kod, który wygenerował powyższe dane wyjściowe.

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

Napisanie i przetestowanie skryptu, który wygenerował powyższe, ujawniło pewne dziwactwa dotyczące tego, jak PowerShell różni się od C #, C, C ++, języka skryptowego poleceń systemu Windows NT i prawie wszystkiego innego, z czym mam jakiekolwiek doświadczenie.


3

Zaczynając od PowerShell 6, otrzymujesz nazwę pliku bez rozszerzenia w następujący sposób:

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

To jest poprawne w PowerShell 6. Nie ma LeafBase w standardzie
bogów

1
Dzięki za informację, odpowiednio zaktualizowałem odpowiedź. Co to jest bagno ?
René Nyffenegger

2
Przepraszam :) skąd pochodzę (Wielka Brytania), „Bog Standard” to slangowe określenie czegoś zupełnie zwyczajnego, wersji „waniliowej”.
finlaybob

2

Ten skrypt wyszukuje w folderze i podfolderach i zmienia nazwy plików, usuwając ich rozszerzenie

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

    Foreach-Object {

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

    }

2

Rozszerzając odpowiedź René Nyffeneggera, dla tych, którzy nie mają dostępu do PowerShell w wersji 6.x, używamy Split Path, który nie testuje istnienia pliku:

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

Zwraca to „ mojplik.txt ”. Jeśli wiemy, że nazwa pliku nie zawiera kropek, możemy podzielić ciąg i wziąć pierwszą część:

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

lub

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

Zwraca „ myfile ”. Jeśli nazwa pliku może zawierać kropki, dla bezpieczeństwa możemy użyć następującego:

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

Zwraca to „ mojplik.txt.config ”. Tutaj wolę używać Substring () zamiast Replace (), ponieważ rozszerzenie poprzedzone kropką może również być częścią nazwy, jak w moim przykładzie. Używając Substring, zwracamy nazwę pliku bez rozszerzenia zgodnie z żądaniem.


1
bardzo dziękuję za tę odpowiedź, jest bardzo kompletna i pomogła mi
Sam


1

Można to zrobić, dzieląc strunę kilka razy.

#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

Oto kod bez komentarzy:

$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
Dlaczego tak ciężko?
Jaroslav Štreit

2
Nie działa, jeśli nazwa pliku zawiera więcej niż jedną kropkę, np. MyApp.exe.config
Joe
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.