2009-06-22 18 views
5

Je souhaite vérifier si un chemin de fichier se trouve dans un répertoire donné (ou l'un de ses sous-répertoires), à partir de PowerShell.Comment vérifier si un fichier se trouve sous un répertoire donné, dans PowerShell?

En ce moment je fais:

$file.StartsWith( $directory, [StringComparison]::InvariantCultureIgnoreCase) 

mais je suis sûr qu'il ya de meilleures façons.

Je pourrais prendre $file.Directory et parcourir tous les .Parent s, mais j'espérais quelque chose de plus simple.

EDIT: le fichier peut ne pas exister; Je regarde juste le chemin.

Répondre

0

quelque chose de réel rapide:

14:47:28 PS>pwd 

C: \ Documents and Settings \ me \ Desktop

14:47:30 PS> $ path = PWD

14:48:03 PS > path $

C: \ Documents and Settings \ me \ Desktop

14:48:16 PS> fichiers $ = Get-ChildItem chemin $ - recurse | Où {$ _. Nom -match "thisfiledoesnt.exist"}

14:50:55 PS> if ($ files) {write-host "le fichier existe dans ce chemin quelque part"} else {write-host " non, il ne "} pas ce ne est pas

(créer un nouveau fichier sur le bureau ou dans un dossier sur le bureau et nommez-le « thisfileexists.txt »)

14:51:03 PS> $ files = Get-ChildItem $ chemin -recurse | Où {$ _. Nom -match "thisfileexists.txt"}

14:52:07 PS> if ($ files) {write-host "le fichier existe dans ce chemin quelque part"} else {write-host " non il ne le fait pas}} le fichier existe dans ce chemin quelque part

Bien sûr, l'itération se produit toujours, mais PS le fait pour vous. Vous pourriez aussi avoir besoin de -force si vous recherchez des fichiers système/cachés.

+0

Je ne suis pas intéressé si le fichier existe, mais si son chemin est sous un répertoire. En outre, votre formatage n'est pas clair. –

+0

Ouais, le formatage de code ici ne fonctionne pas bien pour PS. Ce n'est pas un fichier PS1 complet, juste des choses tapées sur la ligne de cmd PS. Votre question posée "Comment vérifier si un fichier est sous un répertoire donné ..." Il semble que l'autre réponse vérifie également un fichier, comme vous l'avez demandé. Je vois votre édition, mais comment un fichier peut-il avoir un chemin s'il n'existe même pas? – Bratch

+0

Je pense que je comprends maintenant, vous avez ce chemin de fichier stocké quelque part, et vous voulez voir si la partie du chemin existe sous un autre chemin spécifié? – Bratch

5

Que diriez-vous quelque chose d'aussi simple que:

PS> gci . -r foo.txt 

Il utilise implicitement le paramètre -filter (par poste) spécifiant foo.txt comme filtre. Vous pouvez également spécifier * .txt ou foo? .txt. Le problème avec StartsWith est que pendant que vous gérez la comparaison insensible à la casse, il y a toujours le problème que les deux/et \ sont des séparateurs de chemins valides dans PowerShell.

En supposant que le fichier ne peut pas exister et les deux fichier $ et le répertoire $ sont des chemins absolus, vous pouvez le faire le « PowerShell » chemin:

(Split-Path $file -Parent) -replace '/','\' -eq (Get-Item $directory).FullName 

Mais ce n'est pas grand puisque vous avez encore canonique le chemin/-> \ mais au moins la comparaison de chaîne PowerShell est insensible à la casse. Une autre option consiste à utiliser IO.Path pour canaliser le chemin, par ex.:

[io.path]::GetDirectoryName($file) -eq [io.path]::GetFullPath($directory) 

Un problème avec ceci est que GetFullPath sera également un chemin relatif d'un chemin absolu basé sur répertoire courant du processus qui plus souvent qu'autrement, est pas le même que répertoire courant de PowerShell. Donc, assurez-vous que $ directory est un chemin absolu même si vous devez le spécifier comme "$ pwd \ $ directory".

+0

+1. Pouvoir spécifier -path et -fil séparément est très pratique. Apprenez-le, aimez-le. –

0

Quelque chose comme ça?

Get-ChildItem -Recurse $directory | Where-Object { $_.PSIsContainer -and ` 
    $_.FullName -match "^$($file.Parent)" } | Select-Object -First 1 
0

Étant donné que le chemin peut ne pas exister, en utilisant string.StartsWith est très bien pour faire ce type de test (si OrdinalIgnoreCase is a better representation of how the file system compares paths). Le seul inconvénient est que les chemins doivent être sous une forme canonique. Sinon, les chemins d'accès tels que C:\x\..\a\b.txt et C:/a/b.txt échoueront au test "est-ce sous le répertoire C:\a\". Vous pouvez utiliser la méthode Path.GetFullPath statique pour obtenir les noms complets des chemins avant de faire le test:

function Test-SubPath([string]$directory, [string]$subpath) { 
    $dPath = [IO.Path]::GetFullPath($directory) 
    $sPath = [IO.Path]::GetFullPath($subpath) 
    return $sPath.StartsWith($dPath, [StringComparison]::OrdinalIgnoreCase) 
} 

Notez également que cela ne couvre pas le confinement logique (par exemple si vous avez \\some\network\path\ mis en correspondance Z:\path\, vérifier si \\some\network\path\b.txt est en dessous de Z:\ échouera, même si le fichier peut être accessible via Z:\path\b.txt). Si vous devez supporter ce comportement, these questions pourrait vous aider.

0

Si vous convertissez vos chaînes d'entrée en DirectoryInfo et FileInfo, vous n'aurez aucun problème avec la comparaison de chaîne.

function Test-FileInSubPath([System.IO.DirectoryInfo]$Dir,[System.IO.FileInfo]$File) 
{ 
    $File.FullName.StartsWith($Dir.FullName) 
} 
Questions connexes