Видалення шляху та розширення з імені файлу в powershell


99

У мене є ряд рядків, які є повними шляхами до файлів. Я хотів би зберегти лише ім’я файлу, без розширення файлу та провідного шляху. Отже, з цього:

c:\temp\myfile.txt

до

myfile

Я насправді не перебирається через каталог, і в цьому випадку basenameможе використовуватися щось на зразок властивості powershell , але я скоріше маю справу з рядками.


7
багато відповідей не враховують другу частину питання. Коли використовуються Get-Item, Get-ChildItem або їх псевдоніми ls, dir, gi, gci, файл із тестованого рядка повинен існувати . Коли ми перевіряємо ряд рядків і не повторюємо їх через каталог , слід припустити, що ці файли не повинні існувати на комп’ютері, де цей сценарій буде запущений.
папо

Відповіді:


110

Для цього є зручний метод .NET:

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

93

Шлях простіше, ніж я думав, вирішити проблему відображення повного шляху, каталогу, імені файлу чи розширення файлу.

$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

інші форми:

$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
Було б добре, якби поруч із кожним прикладом у фрагменті верхнього коду ви точно вказали, який текст буде повернутий.
смертельної собаки

Приклад, коли я не знаю ім'я файлу .csr, але я знаю, що файл існує: $csr = Get-ChildItem -Path "$($domain.FullName)/*.csr"тодіWrite-Host "fileName: $($csr.Basename)"
Скотт Пелак,

46

Натхненний відповіддю @ walid2mi:

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

Зверніть увагу: це працює лише в тому випадку, якщо даний файл дійсно існує .


1
Це найпростіший спосіб отримати ім'я файлу для одного файлу.
маріски

6
Це передбачає, що файл існує. Видалення розширення з імені файлу не повинно залежати від цього. Що робити, якщо ви створюєте файл на основі імені файлу, де його немає? Шлях - це рядок, і його слід розглядати як рядок, а не вважати його наявним файлом.
Ентоні Бут

29

або

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

або

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

9
Другий приклад не дуже добре працює з чимось на зразок - "C: \ Downloads \ ReSharperSetup.7.0.97.60.msi" .split ('\.') [- 2]
Кіт Хілл

24

ви можете використовувати властивість basename

PS II> ls *.ps1 | select basename

7
ОП говорять: я насправді не перебираю через каталог.
КБ.

1
Дуже корисно для мене!
iheartcsharp

5

@Keith ,

тут ще один варіант:

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

З огляду на будь-який довільний рядок шляху, різні статичні методи на об'єкті System.IO.Path дають такі результати.

strTestPath = C: \ Користувачі \ DAG \ Документи \ Статті_2018 \ NTFS_File_Times_in_CMD \ PathStringInfo.ps1
GetDirectoryName = C: \ Користувачі \ DAG \ Документи \ Статті_2018 \ NTFS_File_Times_in_CMD
GetFileName = PathStringInfo.ps1
GetExtension = .ps1
GetFileNameWithoutExtension = PathStringInfo

Далі йде код, який генерував вищевказаний результат.

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

Написання та тестування сценарію, який генерував вище, розкрив деякі химерності щодо того, чим PowerShell відрізняється від C #, C, C ++, мови скриптових команд Windows NT, і майже всього іншого, з чим у мене є досвід.


3

Починаючи з PowerShell 6, ви отримуєте ім'я файлу без розширення, як-от так:

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

Це правильно в powershell 6. Немає LeafBase в болотному стандарті 5.1
finlaybob

1
Дякую за інформацію, я оновив відповідь відповідно. Що таке болото ?
Рене Ніффенеггер

2
Вибачте :) звідки я (Великобританія), "Bog Standard" - це сленговий термін для чогось, що є абсолютно звичайним, "ванільний" варіант.
finlaybob

2

Цей скрипт здійснює пошук у папці та підпапках та перейменує файли, видаляючи їх розширення

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

    Foreach-Object {

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

    }

2

Розгортаючись на відповідь Рене Ніфенеггера, для тих, хто не має доступу до PowerShell версії 6.x, ми використовуємо Split Path, який не перевіряє наявність файлу:

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

Це повертає " myfile.txt ". Якщо ми знаємо, що в ім’я файлу немає періодів, ми можемо розділити рядок і взяти першу частину:

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

або

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

Це повертає " мій файл ". Якщо ім’я файлу може включати періоди, щоб бути безпечними, ми можемо використовувати наступне:

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

Це повертає " myfile.txt.config ". Тут я вважаю за краще використовувати Substring () замість Replace (), оскільки розширення, яке передує періоду, також може бути частиною назви, як у моєму прикладі. Використовуючи підрядку, ми повертаємо ім'я файлу без розширення, як вимагається.


1
дуже дякую за цю відповідь, вона дуже повна і мені це допомогло
Сем


1

Це можна зробити, розділивши рядок пару разів.

#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

Ось код без коментарів:

$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
Чому такий важкий шлях?
Ярослав Штрейт

2
Не працює, якщо ім'я файлу містить більше одного періоду, наприклад, MyApp.exe.config
Joe
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.