2009-05-03 27 views
17

Tengo un script de PowerShell que recorre un árbol de directorios y, a veces, tengo archivos auxiliares enlazados allí que no deben procesarse. ¿Hay alguna manera fácil de averiguar si un archivo (es decir, System.IO.FileInfo) es un enlace fijo o no?Averigüe si un archivo es un enlace simbólico en PowerShell

Si no, ¿sería más fácil con enlaces simbólicos (enlaces simbólicos)?

Respuesta

30

Prueba esto:

function Test-ReparsePoint([string]$path) { 
    $file = Get-Item $path -Force -ea SilentlyContinue 
    return [bool]($file.Attributes -band [IO.FileAttributes]::ReparsePoint) 
} 

Es una aplicación bastante escaso, pero debe hacer el truco. Tenga en cuenta que esto no distingue entre un enlace rígido y un enlace simbólico. Debajo, ambos solo toman ventaja de NTFS reparse points, IIRC.

+0

Los enlaces duros son simplemente entradas de archivos adicionales en el MFT y, como tales, aparecen como archivos normales, a menos que alguien mire la cantidad de enlaces a ese archivo. Pero no probé un enlace simbólico hasta el momento. De hecho, tiene el conjunto de atributos ReparsePoint. Gracias.(Aunque los enlaces simbólicos son más difíciles de manejar, ya que no tengo permisos para crearlos de manera predeterminada: /) – Joey

+2

Creo que no es cierto que los enlaces permanentes y los enlaces simbólicos usen el mismo mecanismo. Como señaló Johannes, los enlaces duros son solo otra entrada en el MFT. Un enlace simbólico es un punto de análisis. Ellos son diferentes. http://stackoverflow.com/questions/817794/find-out-whether-a-file-is-a-symlink-in-powershell/2255548#2255548 – Cheeso

+0

¿Es posible comprobar también si el enlace simbólico sigue siendo válido? (O en otras palabras, si el directorio de destino no se ha eliminado) –

3

Mis resultados en Vista, utilizando script de PowerShell de Keith Hill para probar enlaces simbólicos o físicos:

c:\markus\other>mklink symlink.doc \temp\2006rsltns.doc 
symbolic link created for symlink.doc <<===>> \temp\2006rsltns.doc 

c:\markus\other>fsutil hardlink create HARDLINK.doc \temp\2006rsltns.doc 
Hardlink created for c:\markus\other\HARDLINK.doc <<===>> c:\temp\2006rsltns.doc 

c:\markus\other>dir 
Volume in drive C has no label. 
Volume Serial Number is C8BC-2EBD 

Directory of c:\markus\other 

02/12/2010 05:21 PM <DIR>   . 
02/12/2010 05:21 PM <DIR>   .. 
01/10/2006 06:12 PM   25,088 HARDLINK.doc 
02/12/2010 05:21 PM <SYMLINK>  symlink.doc [\temp\2006rsltns.doc] 
       2 File(s)   25,088 bytes 
       2 Dir(s) 6,805,803,008 bytes free 

c:\markus\other>powershell \script\IsSymLink.ps1 HARDLINK.doc 
False 

c:\\markus\other>powershell \script\IsSymLink.ps1 symlink.doc 
True 

Esto demuestra que los enlaces simbólicos son los puntos de análisis, y tener el bit de reparsepoint FileAttribute, mientras que los enlaces duros no lo hacen.

2

La siguiente secuencia de comandos de PowerShell mostrará una lista de todos los archivos en un directorio o directorios con el parámetro -recurse. Enumerará el nombre del archivo, ya sea un archivo normal o un archivo de enlace fijo, y el tamaño, separados por dos puntos.

Debe ejecutarse desde la línea de comandos de PowerShell. No importa de qué directorio lo ejecute, ya que está establecido en el script.

Utiliza la utilidad fslink suministrada con Windows y la ejecuta contra cada archivo utilizando el enlace permanente y los conmutadores de lista y cuenta las líneas de salida. Si dos o más es un archivo de enlace fijo.

Por supuesto, puede cambiar el directorio de donde comienza la búsqueda cambiando el c:\windows\system en el comando. Además, la secuencia de comandos simplemente escribe los resultados en un archivo, c:\hardlinks.txt. Puede cambiar el nombre o simplemente eliminar todo del caracter> activado y se enviará a la pantalla.

Get-ChildItem -path C:\Windows\system -file -recurse -force | 
    foreach-object { 
     if ((fsutil hardlink list $_.fullname).count -ge 2) { 
      $_.PSChildname + ":Hardlinked:" + $_.Length 
     } else { 
      $_.PSChildname + ":RegularFile:" + $_.Length 
     } 
    } > c:\hardlinks.txt 
10

Utilice Where-Object para buscar el atributo de archivo ReparsePoint.

Get-ChildItem | Where-Object { $_.Attributes -match "ReparsePoint" } 
+1

Implementación mucho más simple (+1) – user66001

+0

@ user66001 - Sí, pero es una advertencia que esto será mucho más lento para estructuras de carpetas grandes. –

+0

En comparación con las otras respuestas (que existía cuando mi comentario fue hecho)? – user66001

6

Si tiene Powershell 5+ lo siguiente de una sola línea de forma recursiva enumera todos los enlaces duros de archivos, uniones de directorio y enlaces simbólicos y sus objetivos a partir de d:\Temp\:

dir 'd:\Temp' -recurse -force | ?{$_.LinkType} | select FullName,LinkType,Target 

Salida:

FullName        LinkType  Target 
--------        --------  ------ 
D:\Temp\MyJunctionDir     Junction  {D:\exp\junction_target_dir} 
D:\Temp\MySymLinkDir     SymbolicLink {D:\exp\symlink_target_dir} 
D:\Temp\MyHardLinkFile.txt    HardLink  {D:\temp\MyHardLinkFile2.txt, D:\exp\hlink_target.xml} 
D:\Temp\MyHardLinkFile2.txt    HardLink  {D:\temp\MyHardLinkFile.txt, D:\exp\hlink_target.xml} 
D:\Temp\MySymLinkFile.txt    SymbolicLink {D:\exp\symlink_target.xml} 
D:\Temp\MySymLinkDir\MySymLinkFile2.txt SymbolicLink {D:\temp\normal file.txt} 

Si le interesan los objetivos múltiples para enlaces duros, use esta variación que enumera los destinos separados por tabulaciones:

dir 'd:\Temp' -recurse -force | ?{$_.LinkType} | select FullName,LinkType,@{ Name = "Targets"; Expression={$_.Target -join "`t"} } 

Es posible que necesite privilegios de administrador para ejecutar este script en, por ejemplo, C:\.

Cuestiones relacionadas