106 votes

Comment normaliser un chemin dans PowerShell?

J'ai deux chemins:

 fred\frog
 

et

 ..\frag
 

Je peux les réunir dans PowerShell comme ceci:

 join-path 'fred\frog' '..\frag'
 

Cela me donne ceci:

 fred\frog\..\frag
 

Mais je ne veux pas ça. Je veux un chemin normalisé sans les doubles points, comme ceci:

 fred\frag
 

Comment puis-je l'obtenir?

108voto

Shay Levy Points 41404

Vous pouvez développer .. \ frag sur son chemin complet avec resol-path:

 PS > resolve-path ..\frag 
 

Essayez de normaliser le chemin en utilisant la méthode combine ():

 [io.path]::Combine("fred\frog",(resolve-path ..\frag).path)
 

88voto

John Leidegren Points 21951

Vous pouvez utiliser une combinaison d' pwd, Join-Path et [System.IO.Path]::GetFullPath pour obtenir un complet chemin étendu.

Depuis cd (Set-Location) ne modifie pas le processus répertoire de travail en cours, simplement en passant un parent nom de fichier à un .NET API qui n'a pas de comprendre PowerShell contexte, peut avoir des effets secondaires indésirables, tels que la résolution d'un chemin d'accès basé sur le répertoire de travail actif (pas de votre emplacement actuel).

Ce que vous faites, est d'abord qualifier votre chemin:

Join-Path (Join-Path (pwd) fred\frog) '..\frag'

Cette rendements (compte tenu de ma position actuelle):

C:\WINDOWS\system32\fred\frog\..\frag

Avec un absolu de la base, il est possible d'appeler le .NET API GetFullPath:

[System.IO.Path]::GetFullPath((Join-Path (Join-Path (pwd) fred\frog) '..\frag'))

Qui vous donne le chemin d'accès complet et avec l' .. retiré:

C:\WINDOWS\system32\fred\frag

C'est pas compliqué non plus, personnellement, je dédaigne les solutions qui dépendent de scripts externes pour cela, c'est simple problème résolu plutôt bien par Join-Path et pwd (GetFullPath , c'est juste pour faire joli). Si vous ne voulez garder seulement de la part relative, il suffit d'ajouter .Substring((pwd).Path.Trim('\').Length + 1) et le tour est joué!

fred\frag

Mise à JOUR

Grâce à @Dangph pour souligner l' C:\ de cas de bord.

26voto

Charlie Points 17807

Vous pourriez aussi utiliser un Chemin d'accès.GetFullPath, bien que (comme avec R Dan s réponse) ce qui va vous donner le chemin d'accès complet. L'utilisation serait comme suit:

[IO.Path]::GetFullPath( "fred\frog\..\frag" )

ou plus intéressant

[IO.Path]::GetFullPath( (join-path "fred\frog" "..\frag") )

les deux qui produisent la suivante (en supposant que le répertoire courant est D:\):

D:\fred\frag

Notez que cette méthode ne cherche pas à déterminer si fred ou frag existent réellement.

11voto

Jason Stangroome Points 2264

Tout non-PowerShell chemin de fonctions de manipulation (comme dans le Système.IO.Chemin d'accès) ne sera pas fiable à partir de PowerShell parce que PowerShell du modèle de fournisseur permet PowerShell du chemin actuel diffèrent de ce que Windows pense que le processus de " répertoire de travail est.

Aussi, comme vous l'avez peut-être déjà découvert, PowerShell de la détermination du Chemin et de Convertir-le Chemin des applets de commande sont utiles pour convertir des chemins relatifs (ceux contenant '..'s) sur le disque-qualifiés des chemins absolus, mais ils ne parviennent pas si le chemin d'accès référencé n'existe pas.

La suite très simple applet de commande doivent travailler pour les non-existant chemins. Il vous permet de convertir "fred\grenouille\..\frag' à 'd:\fred\frag" même si une 'fred' ou 'frag' fichier ou dossier ne peut pas être trouvé (et l'actuel PowerShell lecteur est 'd:').

function Get-AbsolutePath {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
        [string[]]
        $Path
    )

    process {
        $Path | ForEach-Object {
            $PSCmdlet.SessionState.Path.GetUnresolvedProviderPathFromPSPath($_)
        }
    }
}

3voto

Dangph Points 5561

Cette bibliothèque est bon: NDepend.Les aides.FileDirectoryPath.

EDIT: c'est Ce que je suis venu avec:

[Reflection.Assembly]::LoadFrom("path\to\NDepend.Helpers.FileDirectoryPath.dll") | out-null

Function NormalizePath ($path)
{
    if (-not $path.StartsWith('.\'))  # FilePathRelative requires relative paths to begin with '.'
    {
        $path = ".\$path"
    }

    if ($path -eq '.\.')  # FilePathRelative can't deal with this case
    {
        $result = '.'
    }
    else
    {
        $relPath = New-Object NDepend.Helpers.FileDirectoryPath.FilePathRelative($path)
        $result = $relPath.Path
    }

    if ($result.StartsWith('.\')) # remove '.\'. 
    {
        $result = $result.SubString(2)
    }

    $result
}

L'appeler comme ceci:

> NormalizePath "fred\frog\..\frag"
fred\frag

Notez que cet extrait nécessite le chemin d'accès à la DLL. Il y a un truc que vous pouvez utiliser pour rechercher le dossier contenant le script en cours d'exécution, mais dans mon cas, j'ai eu une variable d'environnement que je pourrais utiliser, donc j'ai simplement utilisé que.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X