Descobrir se um arquivo é um link simbólico no PowerShell
-
03-07-2019 - |
Pergunta
Estou tendo um script PowerShell que está andando uma árvore de diretórios, e às vezes eu tenho arquivos auxiliares hardlinked lá que não deve ser processado. Existe uma maneira fácil de descobrir se um arquivo (ou seja, System.IO.FileInfo
) é um hard link ou não?
Se não, seria mais fácil com links simbólicos (symlinks)?
Solução
Tente isto:
function Test-ReparsePoint([string]$path) {
$file = Get-Item $path -Force -ea SilentlyContinue
return [bool]($file.Attributes -band [IO.FileAttributes]::ReparsePoint)
}
É uma aplicação bastante mínimo, mas deve fazer o truque. Note que isso não faz distinção entre um hard link e um link simbólico. Debaixo, ambos apenas tirar proveito de NTFS nova análise pontos , IIRC .
Outras dicas
Se você tiver PowerShell 5+ o one-liner seguinte forma recursiva lista todos os hardlinks de arquivos, junções de diretório e links simbólicos e seus alvos a partir de 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}
Se você se preocupa com múltiplos alvos para hardlinks usar esta variação que lista-guia separados alvos:
dir 'd:\Temp' -recurse -force | ?{$_.LinkType} | select FullName,LinkType,@{ Name = "Targets"; Expression={$_.Target -join "`t"} }
Você pode precisar de privilégios de administrador para executar este script em C:\
digamos.
Utilize Where-Object
para procurar o atributo de arquivo reparsepoint.
Get-ChildItem | Where-Object { $_.Attributes -match "ReparsePoint" }
Meus resultados no Vista, usando script do PowerShell de Keith Hill para links simbólicos de teste e 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
Isso mostra que links simbólicos são pontos de nova análise, e ter a reparsepoint FileAttribute conjunto de bits, enquanto hardlinks não.
A seguir PowerShell script irá listar todos os arquivos em um diretório ou diretórios com o interruptor -recurse. Ele irá listar o nome do arquivo, se é um arquivo regular ou um arquivo hardlinked, eo tamanho, separados por dois pontos.
Ele deve ser executado a partir da linha de comando PowerShell. Não importa qual diretório você executá-lo a partir de que está definido no script.
Ele usa o utilitário fslink fornecido com o Windows e é executado que contra cada arquivo usando as chaves hardlink e lista e conta as linhas de saída. Se dois ou mais é um arquivo hardlinked.
Você pode, naturalmente, alterar o diretório do início da busca da alterando o c:\windows\system
no comando. Além disso, o script simplesmente grava os resultados para um arquivo, c:\hardlinks.txt
. Você pode alterar o nome ou tudo simplesmente apagar a partir do personagem> e ele vai saída para a tela.
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