Узнайте, является ли файл символической ссылкой в PowerShell

У меня есть сценарий PowerShell, который идет по дереву каталогов, и иногда у меня есть вспомогательные файлы, жестко связанные там, которые не должны обрабатываться. Есть ли простой способ узнать, является ли файл (то есть,System.IO.FileInfo) - Это жесткая ссылка или нет?

если нет, было бы проще с символическими ссылками (символическими ссылками)?

5 ответов


попробуйте это:

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

Это довольно минимальная реализация, но она должна сделать трюк. Обратите внимание, что это не отличает жесткую ссылку от символической ссылки. Под, они оба просто воспользоваться точки повторного разбора NTFS, IIRC.


использовать Where-Object для поиска атрибута файла ReparsePoint.

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

если у вас есть Powershell 5+, следующий однострочный рекурсивно перечисляет все жесткие ссылки на файлы, соединения каталогов и символические ссылки и их цели, начиная с d:\Temp\:

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

выход:

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}

если вы заботитесь о нескольких целях для жестких ссылок, используйте этот вариант, в котором перечислены цели, разделенные вкладками:

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

вам могут потребоваться права администратора для запуска этого сценария на say C:\.


мои результаты в Vista, используя сценарий powershell кита Хилла для тестирования символических и жестких ссылок:

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

c:\markus\other>fsutil hardlink create HARDLINK.doc  \temp06rsltns.doc
Hardlink created for c:\markus\other\HARDLINK.doc <<===>> c:\temp06rsltns.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 [\temp06rsltns.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

он показывает, что символические ссылки являются точками повторной обработки и имеют бит Reparsepoint FileAttribute, а жесткие ссылки-нет.


следующий сценарий PowerShell перечислит все файлы в каталоге или каталогах с параметром-recurse. Он будет перечислять имя файла, будь то обычный файл или файл с жесткой связью, и размер, разделенный двоеточиями.

его необходимо запустить из командной строки PowerShell. Не имеет значения, из какого каталога вы его запускаете, поскольку это задано в скрипте.

он использует утилиту fslink, поставляемую с Windows, и запускает ее для каждого файла с помощью hardlink и список переключает и подсчитывает линии вывода. Если два или больше, это жестко связанный файл.

вы можете, конечно, изменить каталог, из которого начинается поиск, изменив c:\windows\system в командной строке. Кроме того, скрипт просто записывает результаты в файл c:\hardlinks.txt. Вы можете изменить имя или просто удалить все из символа>, и он будет выводиться на экран.

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