2009-06-22 38 views
5

Quiero comprobar si una ruta de archivo está en un directorio determinado (o en uno de sus subdirectorios) desde PowerShell.¿Cómo verifico si un archivo está en un directorio determinado, en PowerShell?

En este momento estoy haciendo:

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

pero estoy seguro de que hay mejores maneras.

Podría hacer tomar $file.Directory e iterar sobre todos .Parent s, pero esperaba algo más simple.

EDIT: el archivo puede no existir; Solo estoy mirando el camino.

Respuesta

0

Algo muy rápido:

14:47:28 PS>pwd 

C: \ Documents and Settings \ me \ Desktop

14:47:30 PS> $ path = pwd

14:48:03 PS > ruta $

C: \ Documents and Settings \ me \ Desktop

14:48:16 PS> $ archivos = Get-ChildItem $ ruta - recurse | Donde {$ _. Nombre -match "thisfiledoesnt.exist"}

14:50:55 PS> if ($ files) {write-host "el archivo existe en esta ruta en alguna parte"} else {write-host " no, no lo hace "} no, no

(crear nuevo archivo en el escritorio o en una carpeta en el escritorio y el nombre 'thisfileexists.txt')

14:51:03 PS> $ files = Get-ChildItem $ path-recursivo | Donde {$ _. Name -match "thisfileexists.txt"}

14:52:07 PD> if ($ files) {write-host "el archivo existe en esta ruta en alguna parte"} else {write-host " no, no "} el archivo existe en esta ruta en alguna parte

Por supuesto, la iteración sigue ocurriendo, pero la PS lo está haciendo por usted. También puede necesitar -force si busca archivos de sistema/ocultos.

+0

No estoy interesado en si el archivo existe, pero si su ruta está bajo un directorio. Además, su formateo no está claro. –

+0

Sí, el formato del código aquí no funciona bien para PS. Este no es un archivo completo de PS1, solo material escrito en la línea de PS cmd. Su pregunta fue "¿Cómo verifico si un archivo está bajo un directorio determinado ...?" Parece que la otra respuesta también está buscando un archivo, como lo pidió. Veo tu edición, pero ¿cómo puede un archivo tener una ruta si ni siquiera existe? – Bratch

+0

Creo que lo entiendo ahora, tiene esta ruta de archivo almacenada en alguna parte, y desea ver si la parte de la ruta existe debajo de alguna otra ruta especificada? – Bratch

5

¿Qué tal algo tan simple como:

PS> gci . -r foo.txt 

Este utiliza implícitamente el parámetro -Filter (por posición) especificando foo.txt como el filtro. También podría especificar * .txt o foo? .txt. El problema con StartsWith es que, mientras maneja la comparación insensible a mayúsculas y minúsculas, todavía existe el problema de que/y \ son separadores de ruta válidos en PowerShell.

Suponiendo que el archivo puede no existir y ambos directorio de archivos $ y $ son las rutas absolutas, puede hacerlo de la manera "PowerShell":

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

Pero eso no es muy grande ya que todavía tiene que canónica la ruta/-> \ pero al menos la comparación de cadena PowerShell no distingue entre mayúsculas y minúsculas. Otra opción es usar IO.Path para canonicalizar la ruta, p.:

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

Un problema con esto es que GetFullPath también hará una ruta relativa una ruta absoluta basada en directorio actual del proceso que más veces que no, es no lo mismo que directorio actual de PowerShell. Así que solo asegúrese de que $ directorio sea una ruta absoluta, incluso si tiene que especificarlo como "$ pwd \ $ directory".

+0

+1. Ser capaz de especificar -path y -fil por separado es muy conveniente. Aprende, ámalo. –

0

¿Algo como esto?

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

Como no podría existir el camino, usando string.StartsWith está muy bien para hacer este tipo de prueba (aunque OrdinalIgnoreCase is a better representation of how the file system compares paths).

La única advertencia es que las rutas deben ser de forma canónica. De lo contrario, las rutas como C:\x\..\a\b.txt y C:/a/b.txt fallarían la prueba "¿está esto bajo el directorio C:\a\". Se puede utilizar el método estático Path.GetFullPath para obtener los nombres completos de los caminos antes de hacer la prueba:

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

También tenga en cuenta que esto no cubre la contención lógica (por ejemplo, si usted tiene \\some\network\path\ asignada a Z:\path\, probando si \\some\network\path\b.txt está bajo Z:\ fallará, aunque se puede acceder al archivo a través de Z:\path\b.txt). Si necesita admitir este comportamiento, puede ser útil these questions.

0

Si convierte sus cadenas de entrada a DirectoryInfo y FileInfo, no tendrá ningún problema con la comparación de cadenas.

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