Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
3
Help us understand the problem. What is going on with this article?
@nukie_53

全てのジャンクションを解決したパスを取得したい

More than 3 years have passed since last update.

あるパスから全てのジャンクションを解決したパス(要するに本来の場所のパス)を取得したいと思った。
汚いなりに形が出来たと喜んだのも束の間、対象としたいWindows7(PowerShell v2.0)では動かなそうなことが判明。

とりあえず現状を備忘録として残す。

思考の流れ

  1. Get-Item 'フォルダパス'System.IO.DirectoryInfoを取得すれば、Attributeからリパースポイント(ジャンクションなど)かどうかわかる(参考)。

  2. 一階層ずつジャンクションかどうか判断し、ジャンクションなら本来の場所へ移動して、また登って行けば良い。

  3. ルートフォルダまで辿り着いたら探索終了とし、それまで通ってきたフォルダの履歴をパスとして接合する。

出来上がったもの

Solve-JunctionPath.ps1
#引数の設定
Param(
    [Parameter (Mandatory=$true)]
    [String]$FilePath #=$Args[0]
)

[IO.FileSystemInfo]$argPath=Get-Item $FilePath

#一階層毎のフォルダ名配列 Leaf To Root
[Collections.Generic.IList[String]]$DirNameList = New-Object -TypeName Collections.Generic.List[String]


if ($argPath.Attributes -like "*Directory*")
{
    [IO.DirectoryInfo]$tmpDir = $argPath
} else {
    [IO.DirectoryInfo]$tmpDir = $argPath.Directory
}

do
{
    if ($tmpDir.Attributes -like "*ReparsePoint*")
    {
        $tmpDir = Get-Item $tmpDir.Target
    }

    #ジャンクション解決後のフォルダ名を取得する
    $DirNameList.Add($tmpDir.Name)

    $tmpDir = $tmpDir.Parent
}
until($tmpDir.FullName -eq $tmpDir.Root.FullName)

#Root To Leaf
$DirNameList.Reverse()


[String]$out = $tmpDir.FullName + ($DirNameList -join '\')

#フォルダを開く
Explorer.exe $out
#結果確認用
#$out

使用例

上記のコードを"Solve-JunctionPath.ps1"という名前で保存し、同じ場所に以下のようなbatファイルを作成する。

@PowerShell.exe -ExecutionPolicy RemoteSigned %~dp0\Solve-JunctionPath.ps1 '%~1'

このバッチファイルに調べたいパスを送ると、本来の場所のフォルダが開く。

問題の箇所

    if ($tmpDir.Attributes -like "*ReparsePoint*")
    {
        $tmpDir=Get-Item $tmpDir.Target
    }

PowerShell 2.0では
(161110修正)
DirectoryInfoのAttributesに再解析ポイントかどうかの情報を持たないので、
リンク先本来の場所の情報を持たない(.Targetプロパティが存在しない)ため、
この方法では辿ることができない。

実際、Get-Memberをしてみると.TargetプロパティはCodePropertyとなっている。
つまりPowerShell側で追加されたプロパティであるため、PowerShellのバージョンが低いと存在しないということになる。

対応策

とりあえず思いつく解決策としては、
cmd.exe /c dir "ディレクトリパス" /AL
の出力結果を正規表現なりで解析する方法。

更新日時 <JUNCTION> ジャンクション名 [参照先]
の形式で取得できるのでジャンクション名で判定し、参照先へ移動、すれば何とかなると思われる。

参考

PowerShell で シンボリックリンクを 使えるようにしよう
PowerShellでジャンクションを作ったら削除はRomove-Itemしてはダメ

3
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
nukie_53
Excel・PowerPoint の VBA、Windows PowerShell がメインの人です。 Word・Outlook の VBA も多少は読めます。 データベース関連や、管理用途の PowerShell は経験なし。 PowerShell の延長で、C# も雰囲気は読める感じです。

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
3
Help us understand the problem. What is going on with this article?