powershell symlink hardlink

Averigüe si un archivo es un enlace simbólico en PowerShell



symlink hardlink (5)

Tengo una secuencia de comandos de PowerShell que recorre un árbol de directorios y, a veces, tengo archivos auxiliares enlazados allí que no deberían procesarse. ¿Hay una manera fácil de averiguar si un archivo (es decir, System.IO.FileInfo ) es un enlace duro o no?

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


El siguiente script de PowerShell listará todos los archivos en un directorio o directorios con el interruptor -recurse. Enumera el nombre del archivo, ya sea un archivo normal o un archivo de enlace rígido, y el tamaño, separados por dos puntos.

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

Utiliza la utilidad fslink suministrada con Windows y la ejecuta contra cada archivo usando los vínculos de enlace y lista fija y cuenta las líneas de salida. Si dos o más es un archivo enlazado.

Por supuesto, puede cambiar el directorio desde el que comienza la búsqueda cambiando 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 desde el carácter> y saldrá 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


Mis resultados en Vista, utilizando el script powershell de Keith Hill para probar enlaces simbólicos y enlaces 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

Muestra que los enlaces simbólicos son puntos de análisis y que tienen establecido el bit ReparsePoint FileAttribute, mientras que los enlaces físicos no lo tienen.


Prueba esto:

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

Es una implementación bastante mínima, pero debería hacer el truco. Tenga en cuenta que esto no distingue entre un enlace físico y un enlace simbólico. Debajo, ambos se aprovechan de los puntos de análisis NTFS , IIRC .


Si tiene Powershell 5+, la siguiente línea de un solo uso recursivamente enumera todos los enlaces físicos de archivos, uniones de directorios y enlaces simbólicos y sus destinos 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 preocupan los múltiples destinos para enlaces duros, use esta variación que enumera los objetivos separados por tabuladores:

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:/ .


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

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