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.

larryq
źródło
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
Keith Hill
źródło
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)
Leonardo
źródło
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 .

CodeFox
źródło
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]
walid2mi
źródło
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
walid2mi
źródło
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]
walid2mi
źródło
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.

David A. Gray
źródło
3

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

split-path c:\temp\myfile.txt -leafBase
René Nyffenegger
źródło
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

    }
user12386990
źródło
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.

Papa Ccompis
źródło
1
bardzo dziękuję za tę odpowiedź, jest bardzo kompletna i pomogła mi
Sam
1

Oto jeden bez nawiasów

[io.fileinfo] 'c:\temp\myfile.txt' | % basename
Steven Penny
źródło
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
OneOfThePetes
źródło
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