2009-05-03 22 views
17

Tôi đang sử dụng tập lệnh PowerShell đang đi trên cây thư mục và đôi khi tôi có các tệp phụ được liên kết cứng ở đó không nên xử lý. Có một cách dễ dàng để tìm hiểu xem một tập tin (có nghĩa là, System.IO.FileInfo) là một liên kết cứng hay không?Tìm hiểu xem tệp có phải là một liên kết tượng trưng trong PowerShell

Nếu không, sẽ dễ dàng hơn với các liên kết tượng trưng (liên kết tượng trưng)?

Trả lời

30

Hãy thử điều này:

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

Đó là một thực hiện khá tối thiểu, nhưng nó phải làm các trick. Lưu ý rằng điều này không phân biệt giữa liên kết cứng và liên kết tượng trưng. Bên dưới, cả hai đều tận dụng lợi thế của NTFS reparse points, IIRC.

+0

Liên kết cứng chỉ đơn giản là các mục nhập tệp bổ sung trong MFT và như vậy xuất hiện dưới dạng tệp bình thường, trừ khi ai đó xem xét số lượng liên kết đến tệp đó. Nhưng tôi đã không thử một liên kết tượng trưng cho đến nay. Thật vậy nó có tập thuộc tính ReparsePoint. Cảm ơn.(Mặc dù symlink có nhiều cồng kềnh hơn để xử lý, vì tôi không có quyền tạo chúng theo mặc định: /) – Joey

+2

Tôi nghĩ rằng các liên kết cứng và symlink không sử dụng cùng một cơ chế. Như Johannes đã chỉ ra, các liên kết cứng chỉ là một mục nhập khác trong MFT. Một liên kết tượng trưng là một điểm Reparse. Chúng khác nhau. http://stackoverflow.com/questions/817794/find-out-whether-a-file-is-a-symlink-in-powershell/2255548#2255548 – Cheeso

+0

Có khả năng nó cũng kiểm tra xem liên kết tượng trưng vẫn hợp lệ không? (Hay nói cách khác, nếu thư mục đích chưa bị xóa) –

3

kết quả của tôi trên Vista, sử dụng kịch bản PowerShell Keith Hill để kiểm tra liên kết tượng trưng và hardlinks:

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 

Nó cho thấy rằng liên kết tượng trưng là những điểm reparse, và có ReparsePoint FileAttribute bit được thiết lập, trong khi liên kết cứng thì không.

2

Tập lệnh PowerShell sau đây sẽ liệt kê tất cả các tệp trong một thư mục hoặc thư mục có công tắc -recurse. Nó sẽ liệt kê tên của tệp, cho dù đó là tệp thông thường hoặc tệp liên kết cứng và kích thước, được phân tách bằng dấu hai chấm.

Nó phải được chạy từ dòng lệnh PowerShell. Nó không quan trọng bạn sẽ chạy thư mục nào từ thư mục được đặt trong tập lệnh.

Nó sử dụng tiện ích fslink được vận chuyển bằng Windows và chạy nó với mỗi tệp bằng cách sử dụng liên kết cứng và danh sách và đếm dòng đầu ra. Nếu hai hoặc lớn hơn nó là một tập tin liên kết cứng.

Bạn có thể thay đổi thư mục mà tìm kiếm bắt đầu bằng cách thay đổi c:\windows\system trong lệnh. Ngoài ra, tập lệnh chỉ cần viết kết quả vào một tệp, c:\hardlinks.txt. Bạn có thể thay đổi tên hoặc chỉ cần xóa mọi thứ từ ký tự> và nó sẽ xuất ra màn hình.

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

Sử dụng Where-Object để tìm kiếm thuộc tính tệp ReparsePoint.

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

Thực hiện đơn giản hơn nhiều (+1) – user66001

+0

@ user66001 - Có một đơn giản nhưng có một thông báo trước rằng điều này sẽ chậm hơn rất nhiều đối với các cấu trúc thư mục lớn. –

+0

So với các câu trả lời khác (đã tồn tại khi nhận xét của tôi đã được đưa ra)? – user66001

6

Nếu bạn có Powershell 5 + sau một lót đệ quy liệt kê tất cả hardlinks tập tin, thư mục và các nút liên kết tượng trưng và mục tiêu của họ bắt đầu từ d:\Temp\:

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

Output:

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} 

Nếu bạn quan tâm đến nhiều mục tiêu cho liên kết cứng, hãy sử dụng biến thể này liệt kê các mục tiêu được phân tách bằng tab:

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

Bạn có thể cần đặc quyền của quản trị viên để chạy tập lệnh này theo số C:\.