Eliminando la ruta y la extensión del nombre de archivo en powershell


99

Tengo una serie de cadenas que son rutas completas a los archivos. Me gustaría guardar solo el nombre del archivo, sin la extensión del archivo y la ruta principal. Entonces de esto:

c:\temp\myfile.txt

a

myfile

En realidad, no estoy iterando a través de un directorio, en cuyo caso se basenamepodría usar algo como la propiedad de powershell , sino que estoy tratando solo con cadenas.


7
muchas respuestas no tienen en cuenta la segunda parte de la pregunta. Cuando se utilizan Get-Item, Get-ChildItem o sus alias ls, dir, gi, gci, el archivo de la cadena probada debe existir . Cuando estamos comprobando una serie de cadenas y no iterando a través de un directorio , se debe asumir que esos archivos no necesitan existir en la computadora donde se ejecutará este script.
papo

Respuestas:


110

Hay un método .NET útil para eso:

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

93

Es mucho más fácil de lo que pensaba abordar el problema de mostrar la ruta completa, el directorio, el nombre del archivo o la extensión del archivo.

$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

otras formas:

$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
Sería bueno si al lado de cada ejemplo en el fragmento de código superior mostrara exactamente qué texto se devolvería.
deadlydog

Ejemplo en el que no sé el nombre del archivo .csr, pero sé que existe un archivo: $csr = Get-ChildItem -Path "$($domain.FullName)/*.csr"entoncesWrite-Host "fileName: $($csr.Basename)"
Scott Pelak

46

Inspirado por una respuesta de @ walid2mi:

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

Tenga en cuenta: esto solo funciona si el archivo dado realmente existe .


1
Esta es la forma más fácil de obtener el nombre de archivo para un solo archivo.
marzo

6
Esto supone que el archivo existe. Eliminar una extensión de un nombre de archivo no debería depender de eso. ¿Qué sucede si está creando un archivo basado en un nombre de archivo donde el archivo no existe? La ruta es una cadena y debe tratarse como una cadena, no se supone que sea un archivo existente.
Antony Booth

29

o

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

o

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

9
El segundo ejemplo no funciona muy bien con algo como: "C: \ Downloads \ ReSharperSetup.7.0.97.60.msi" .split ('\.') [- 2]
Keith Hill

24

puedes usar la propiedad basename

PS II> ls *.ps1 | select basename

7
El OP dice: en realidad no estoy iterando a través de un directorio.
CB.

1
¡Muy útil para mí!
iheartcsharp

5

@Keith ,

aquí otra opción:

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

Dada cualquier cadena de ruta arbitraria, varios métodos estáticos en el objeto System.IO.Path dan los siguientes resultados.

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

A continuación se muestra el código que generó el resultado anterior.

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

Escribir y probar el script que generó lo anterior descubrió algunas peculiaridades sobre cómo PowerShell se diferencia de C #, C, C ++, el lenguaje de script de comandos de Windows NT y casi todo lo demás con el que tengo experiencia.


3

A partir de PowerShell 6, obtiene el nombre de archivo sin extensión así:

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

Esto es correcto en powershell 6. No hay LeafBase en bog standard 5.1
finlaybob

1
Gracias por la información, he actualizado la respuesta en consecuencia. ¿Qué es el pantano ?
René Nyffenegger

2
Disculpas :) de donde soy (Reino Unido), "Bog Standard" es un término del argot para algo que es completamente ordinario, una versión "vainilla".
finlaybob

2

Este script busca en una carpeta y subcarpetas y cambia el nombre de los archivos eliminando su extensión.

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

    Foreach-Object {

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

    }

2

Ampliando la respuesta de René Nyffenegger, para aquellos que no tienen acceso a la versión 6.x de PowerShell, usamos Split Path, que no prueba la existencia de archivos:

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

Esto devuelve " myfile.txt ". Si sabemos que el nombre del archivo no tiene puntos, podemos dividir la cadena y tomar la primera parte:

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

o

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

Esto devuelve " myfile ". Si el nombre del archivo puede incluir puntos, para estar seguros, podríamos usar lo siguiente:

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

Esto devuelve " myfile.txt.config ". Aquí prefiero usar Substring () en lugar de Replace () porque la extensión precedida por un punto también podría ser parte del nombre, como en mi ejemplo. Al usar Substring, devolvemos el nombre del archivo sin la extensión solicitada.


1
muchas gracias por esta respuesta, es muy completa y me ayudó
Sam

1

Aquí hay uno sin paréntesis

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

1

Esto se puede hacer dividiendo la cuerda un par de veces.

#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

Aquí está el código sin comentarios:

$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
¿Por qué tan difícil?
Jaroslav Štreit

2
No funciona si el nombre del archivo contiene más de un punto, por ejemplo, MyApp.exe.config
Joe
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.