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)?

Foi útil?

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
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top