Suppression du chemin et de l'extension du nom de fichier dans PowerShell


99

J'ai une série de chaînes qui sont des chemins complets vers des fichiers. Je voudrais enregistrer uniquement le nom de fichier, sans l'extension de fichier et le chemin principal. Donc à partir de ceci:

c:\temp\myfile.txt

à

myfile

Je ne suis pas en train d'itérer dans un répertoire, auquel cas quelque chose comme la basenamepropriété de PowerShell pourrait être utilisé, mais je ne m'occupe que de chaînes.


7
de nombreuses réponses ne tiennent pas compte de la deuxième partie de la question. Lorsque Get-Item, Get-ChildItem ou leurs alias ls, dir, gi, gci sont utilisés, le fichier de la chaîne testée doit exister . Lorsque nous vérifions une série de chaînes et n'effectuons pas d' itérations dans un répertoire , il faut supposer que ces fichiers n'ont pas besoin d'exister sur l'ordinateur sur lequel ce script sera exécuté.
papo

Réponses:


110

Il existe une méthode .NET pratique pour cela:

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

93

Beaucoup plus facile que je ne le pensais pour résoudre le problème de l'affichage du chemin complet, du répertoire, du nom de fichier ou de l'extension de fichier.

$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

autres formes:

$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
Ce serait bien si à côté de chaque exemple dans l'extrait de code supérieur, vous montriez exactement quel texte serait retourné.
deadlydog

Exemple où je ne connais pas le nom de fichier .csr, mais je sais qu'un fichier existe: $csr = Get-ChildItem -Path "$($domain.FullName)/*.csr"alorsWrite-Host "fileName: $($csr.Basename)"
Scott Pelak

46

Inspiré d'une réponse de @ walid2mi:

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

Remarque: cela ne fonctionne que si le fichier donné existe vraiment .


1
C'est le moyen le plus simple d'obtenir le nom de fichier pour un seul fichier.
marisks le

6
Cela suppose que le fichier existe. La suppression d'une extension d'un nom de fichier ne devrait pas en dépendre. Que faire si vous créez un fichier basé sur un nom de fichier où le fichier n'existe pas? Le chemin d'accès est une chaîne et doit être traité comme une chaîne, pas supposé être un fichier existant.
Antony Booth

29

ou

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

ou

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

9
Le deuxième exemple ne fonctionne pas très bien avec quelque chose comme - "C: \ Downloads \ ReSharperSetup.7.0.97.60.msi" .split ('\.') [- 2]
Keith Hill

24

vous pouvez utiliser la propriété basename

PS II> ls *.ps1 | select basename

7
L'OP dit: je ne suis pas en train d'itérer dans un répertoire.
CB.

1
Très utile pour moi!
iheartcsharp

5

@Keith ,

voici une autre option:

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

Étant donné toute chaîne de chemin arbitraire, diverses méthodes statiques sur l'objet System.IO.Path donnent les résultats suivants.

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

Voici le code qui a généré la sortie ci-dessus.

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

L'écriture et le test du script qui a généré ce qui précède ont révélé certaines bizarreries sur la différence entre PowerShell et C #, C, C ++, le langage de script de commande Windows NT et à peu près tout le reste avec lequel j'ai une expérience.


3

À partir de PowerShell 6, vous obtenez le nom de fichier sans extension comme ceci:

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

C'est correct dans PowerShell 6. Il n'y a pas de LeafBase dans la norme bog 5.1
finlaybob

1
Merci pour l'info, j'ai mis à jour la réponse en conséquence. Qu'est-ce que la tourbière ?
René Nyffenegger

2
Excuses :) d'où je viens (Royaume-Uni), "Bog Standard" est un terme d'argot pour quelque chose qui est complètement ordinaire, une version "vanille".
finlaybob

2

Ce script recherche dans un dossier et des sous-dossiers et renomme les fichiers en supprimant leur extension

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

    Foreach-Object {

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

    }

2

En développant la réponse de René Nyffenegger, pour ceux qui n'ont pas accès à PowerShell version 6.x, nous utilisons Split Path, qui ne teste pas l'existence de fichiers:

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

Cela renvoie " myfile.txt ". Si nous savons que le nom du fichier ne contient pas de points, nous pouvons diviser la chaîne et prendre la première partie:

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

ou

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

Cela renvoie " myfile ". Si le nom du fichier peut inclure des points, pour être sûr, nous pourrions utiliser ce qui suit:

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

Cela renvoie " myfile.txt.config ". Ici, je préfère utiliser Substring () au lieu de Replace () car l'extension précédée d'un point pourrait également faire partie du nom, comme dans mon exemple. En utilisant Substring, nous renvoyons le nom de fichier sans l'extension comme demandé.


1
merci beaucoup pour cette réponse, elle est très complète et elle m'a aidé
Sam

1

En voici un sans parenthèses

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

1

Cela peut être fait en divisant la chaîne plusieurs fois.

#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

Voici le code sans commentaires:

$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
Pourquoi si difficile?
Jaroslav Štreit

2
Ne fonctionne pas si le nom de fichier contient plus d'un point, par exemple MyApp.exe.config
Joe
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.