Удаление пути и расширения из имени файла в PowerShell

100

У меня есть серия строк, которые представляют собой полные пути к файлам. Я хочу сохранить только имя файла без расширения файла и ведущего пути. Итак, из этого:

c:\temp\myfile.txt

к

myfile

На самом деле я не выполняю итерацию по каталогу, и в этом случае basenameможно использовать что-то вроде свойства powershell , а я имею дело только со строками.

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

Ответы:

111

Для этого есть удобный метод .NET:

C:\PS> [io.path]::GetFileNameWithoutExtension("c:\temp\myfile.txt")
myfile
Кейт Хилл
источник
94

Намного проще, чем я думал, решить проблему отображения полного пути, каталога, имени файла или расширения файла.

$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
Было бы неплохо, если бы рядом с каждым примером в верхнем фрагменте кода вы указали, какой именно текст будет возвращен.
deadlydog
Пример, когда я не знаю имя файла .csr, но знаю, что файл существует: $csr = Get-ChildItem -Path "$($domain.FullName)/*.csr"затемWrite-Host "fileName: $($csr.Basename)"
Скотт Пелак
46

На основе ответа @ walid2mi:

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

Обратите внимание: это работает, только если данный файл действительно существует .

CodeFox
источник
1
Это самый простой способ получить имя файла для отдельного файла.
marisks
6
Предполагается, что файл существует. Удаление расширения из имени файла не должно зависеть от этого. Что, если вы создаете файл на основе имени файла, в котором файл не существует? Путь - это строка, которую следует рассматривать как строку, а не как существующий файл.
Энтони Бут,
29

или

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

или

"c:\temp\myfile.txt".split('\.')[-2]
walid2mi
источник
9
Второй пример не очень хорошо работает с чем-то вроде - "C: \ Downloads \ ReSharperSetup.7.0.97.60.msi" .split ('\.') [- 2]
Кейт Хилл
24

вы можете использовать свойство basename

PS II> ls *.ps1 | select basename
walid2mi
источник
7
OP говорит: я на самом деле не повторяю каталог.
CB.
1
Очень полезно для меня!
iheartcsharp
5

@ Кит ,

вот еще вариант:

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
источник
4

Для любой произвольной строки пути различные статические методы объекта System.IO.Path дают следующие результаты.

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

Ниже приведен код, сгенерировавший вышеуказанный вывод.

[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. В стандарте болота 5.1 нет LeafBase
finlaybob
1
Спасибо за информацию, я обновил ответ соответственно. Что такое болото ?
René Nyffenegger
2
Извинения :) где я родом (Великобритания), «Bog Standard» - это жаргонный термин для чего-то совершенно обычного, «ванильной» версии.
Finlaybob
2

Этот скрипт ищет в папке и подпапках и переименовывает файлы, удаляя их расширение.

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

    Foreach-Object {

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

    }
user12386990
источник
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]

Это возвращает « myfile ». Если имя файла может включать точки, на всякий случай можно использовать следующее:

$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 (), потому что расширение, которому предшествует точка, также может быть частью имени, как в моем примере. Используя Substring, мы возвращаем имя файла без расширения по запросу.

Папа Компис
источник
1
Большое спасибо за этот ответ, он очень полный, и он мне помог
Сэм
1

Вот без скобок

[io.fileinfo] 'c:\temp\myfile.txt' | % basename
Стивен Пенни
источник
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
OneOfThePetes
источник
1
Почему так тяжело?
Ярослав Штрейт
2
Не работает, если имя файла содержит более одной точки, например MyApp.exe.config
Джо,