Test in PowerShell code if a folder is a junction point?
Asked Answered
E

7

8

How can I test in PowerShell code if a folder is a junction point?

Endomorphic answered 22/2, 2010 at 13:28 Comment(1)
Are you going to mark a post as the right answer?Penetrating
P
5

Take a look at this blog: https://web.archive.org/web/20190422210654/https://devblogs.microsoft.com/powershell/viewing-junctions-with-dir/

the way to do it is to copy the built in file system formatting file, modify it so that junctions are indicated, then load it with Update-FormatData:

From the Blog:

The file system formatting rules are in $pshome\FileSystem.Format.ps1xml. I copied this, then in the element [ViewDefinitions –> View –> TableControl –> TableRowEntries –> TableRowEntry –> TableColumnItems –> TableColumnItem] I changed the content of PropertyName with value of 'Mode' to the following:

<ScriptBlock> 
   "$($_.Mode)$(if($_.Attributes -band [IO.FileAttributes]::ReparsePoint)
{'J'})" </ScriptBlock> 

This does a bitwise AND on the DirectoryInfo object Attributes property ($_.Attributes) against the .Net System.IO.FileAttributes.ReparsePoint enum value. If the result is not zero, it displays a ‘J’ next to the other file mode attributes. Next, load the new formatting file like this:

 PS> Update-FormatData -PrependPath myFilesystem.format.ps1xml

The PrependPath parameter ensures that the new formatting file is loaded before the built-in formatting files.

Directory alink has a ‘J’ in the mode column, seems to work!

It's in the Mode column J for Junction.

Penetrating answered 22/2, 2010 at 13:34 Comment(0)
E
10

Since at least PowerShell v5.0, there is better support for links (or as MS calls them: Reparse Points)

improved Item cmdlets - LinkType property

Linked article is under WMF 5.0 category, which might mean that the method was available since PS v5.0.
These features were included in standard Get-Item, Get-ChildItem, so there are no additional steps required. It can be used on any current PS.

LinkType is a String property on an Object, returned by Get-Item and Get-ChildItem,
it can have one of the following four values: '', 'Junction', 'SymbolicLink', 'HardLink'.

To answer OP's question, you can check if a folder is a junction point using:

if ((Get-Item -Path $Target -Force).LinkType -eq "Junction") { }

To check if a file/folder is a "ReparsePoint", of any kind (Junction, SymbolicLink or HardLink):

if ((Get-Item -Path $Target -Force).LinkType) { }

LinkType value on ordinary file/folder is an empty String, which when used as if condition in PS resolves to False


Get-ChildItem can be used to list all Junction folders:

(Get-ChildItem -Path $Target -Force) | Where-Object { $_.LinkType -eq "Junction" }

Note that value 'SymbolicLink' is the same for both file or folder, so to list only Symbolic links to folders:

(Get-ChildItem -Path $Target -Directory -Force) | Where-Object { $_.LinkType -eq "SymbolicLink" }


Cmdlet Get-ChildItem (alias: dir, ls, gci) now shows ReparsePoint attribute, as l in Mode column, without any extension. But it will not show 'HardLink' and shows l for both Junction and SymbolicLink:

> Get-ChildItem -Path $Target -Force


    Directory: C:\Users


Mode                LastWriteTime         Length Name                          
----                -------------         ------ ----                          
d--hsl       2018-04-12     01:45                All Users                     
d-rh--       2018-05-09     06:12                Default                       
d--hsl       2018-04-12     01:45                Default User                  
d-----       2018-06-24     03:05                Papo                          
d-r---       2018-07-27     07:12                Public
  • LinkType does not work on folders with special permissions inside \Users and \Users\, even though Get-ChildItem as seen above does work and shows l on them.
  • Remove-Item has issues. It can't remove Junction, and if Forced, will remove original contents with it. This is said to be fixed in future version PS v6

Using these improved, or today's standard Cmdlets, has some advantages over previous methods, described in older answers here.

  • It does differentiate between Junction and Symbolic Link
    If OP wanted to test if folder is a Junction, checking by Attribute property would result in false positive for folder Symbolic Link.

  • detects Hard Link.

  • LinkType is [String] as opposed to Attributes property, which is [FileAttributes] type and needs .ToString() or a use of -band

Epileptoid answered 27/7, 2018 at 17:52 Comment(2)
It's not just "Users" that LinkType doesn't work on. For example, on my computer running W10 with PS 5.1, LinkType is null for both "C:\Documents and Settings" and "C:\ProgramData\Desktop", whereas dir /aL (Command Prompt, not PowerShell) indicates they are both junction points. LinkType just does not appear to be reliable for reparse points.Brunner
Very comprehensive answer that should be ranked higher for anyone using a modern PowerShell release.Bulgarian
R
7

If (Get-Item Test Folder).Attributes.ToString().Contains("ReparsePoint"){Code}

Romonaromonda answered 24/7, 2013 at 13:56 Comment(3)
This is the only solution that does not rely on changing PowerShell config files or using third party extensions. An alternative version is: if ((Get-Item Test Folder).Attributes -match [System.IO.FileAttributes]::ReparsePoint){Code}Gump
The OP asked for a programmatic solution, and this is just that.Igorot
That's a test for any type of reparse points and will be true for other non-junction reparse points such as NTFS symbolic links and volume mount points. See papo's answer for how to differentiate between the varous types of reparse points in recent releases of PowerShell.Bulgarian
P
5

Take a look at this blog: https://web.archive.org/web/20190422210654/https://devblogs.microsoft.com/powershell/viewing-junctions-with-dir/

the way to do it is to copy the built in file system formatting file, modify it so that junctions are indicated, then load it with Update-FormatData:

From the Blog:

The file system formatting rules are in $pshome\FileSystem.Format.ps1xml. I copied this, then in the element [ViewDefinitions –> View –> TableControl –> TableRowEntries –> TableRowEntry –> TableColumnItems –> TableColumnItem] I changed the content of PropertyName with value of 'Mode' to the following:

<ScriptBlock> 
   "$($_.Mode)$(if($_.Attributes -band [IO.FileAttributes]::ReparsePoint)
{'J'})" </ScriptBlock> 

This does a bitwise AND on the DirectoryInfo object Attributes property ($_.Attributes) against the .Net System.IO.FileAttributes.ReparsePoint enum value. If the result is not zero, it displays a ‘J’ next to the other file mode attributes. Next, load the new formatting file like this:

 PS> Update-FormatData -PrependPath myFilesystem.format.ps1xml

The PrependPath parameter ensures that the new formatting file is loaded before the built-in formatting files.

Directory alink has a ‘J’ in the mode column, seems to work!

It's in the Mode column J for Junction.

Penetrating answered 22/2, 2010 at 13:34 Comment(0)
D
1

FYI, if you happen to be running PowerShell Community Extensions, this info is available as output (and as a note property) on output of Get-ChildItem:

21> gci .\Roaming\Microsoft\eHome


    Directory: Microsoft.PowerShell.Core\FileSystem::C:\Users...


Mode           LastWriteTime       Length Name
----           -------------       ------ ----
d----     2/15/2010 12:18 AM        <DIR> DvdCoverCache
d----      8/9/2009  1:10 AM    <SYMLINK> DvdInfoCache [\...
d----      8/8/2009 11:51 PM        <DIR> DvdInfoCache.orig
d----    10/22/2009  7:12 PM        <DIR> mcl_images

However for programmatic access I would access the info via the Attributes property as the other poster suggests.

Danaus answered 22/2, 2010 at 15:20 Comment(0)
A
0

If you have the PowerShell Community Extensions which I would recommend if you are working with junctions you can do the following to determine if a folder is a junction or not:

Import-Module pscx
if ((Get-Item *test_folder*).ReparsePoint){
    Write-Host "YES"
}
Adamson answered 23/6, 2011 at 14:35 Comment(0)
M
0

Try this:

$TargetAttributes = (Get-Item -Path $Target -Force).Attributes.ToString()
if ($TargetAttributes -match "ReparsePoint") {
    if ($TargetAttributes -match "Archive") {
        Write-Output ("Link to a file.")
    } else {
        Write-Output ("Link to a folder.")
    }
} else {
    Write-Output ("Normal File or Folder.")
}    
Massif answered 6/4, 2018 at 9:56 Comment(0)
I
0

Example for exclude Junction from listing (or "-match", for exclude all another):

(Get-ChildItem -Force | where {$_.PSIsContainer -eq $true -And $_.Attributes -notmatch "Reparse"})
Illuminate answered 2/2, 2023 at 14:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.