Skip to content

Fix Remove-Item <symbolic link to directory> #621

Closed

Description

If you make a symbolic link to a directory on Windows (with administrative privileges of course), and then try to delete said link, you get this:

|Y> Yes |A> Yes to All |N> No |L> No to All |S> Suspend [Default is (Y]
PS C:\Users\anschwa\src\PowerShell> remove-item -Force .\foobar\
Confirm
The item at C:\Users\anschwa\src\PowerShell\foobar\ has children and the Recurse parameter was not specified. If you con
tinue, all children will be removed with the item. Are you sure you want to continue?

|Y> Yes |A> Yes to All |N> No |L> No to All |S> Suspend [Default is (Y]
n
PS C:\Users\anschwa\src\PowerShell> remove-item -Force .\foobar\ -Recurse
remove-item : There is a mismatch between the tag specified in the request and the tag present in the reparse point
At line:1 char:1
+ remove-item -Force .\foobar\ -Recurse
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Remove-Item], Win32Exception
    + FullyQualifiedErrorId : System.ComponentModel.Win32Exception,Microsoft.PowerShell.Commands.RemoveItemCommand

PS C:\Users\anschwa\src\PowerShell> $error[0].Exception.StackTrace
   at Microsoft.PowerShell.Commands.InternalSymbolicLinkLinkCodeMethods.DeleteJunction(String junctionPath) in C:\Users\
anschwa\src\PowerShell\src\monad\monad\src\namespaces\FileSystemProvider.cs:line 8447
   at Microsoft.PowerShell.Commands.FileSystemProvider.RemoveDirectoryInfoItem(DirectoryInfo directory, Boolean recurse,
 Boolean force, Boolean rootOfRemoval) in C:\Users\anschwa\src\PowerShell\src\monad\monad\src\namespaces\FileSystemProvi
der.cs:line 2859
   at Microsoft.PowerShell.Commands.FileSystemProvider.RemoveItem(String path, Boolean recurse) in C:\Users\anschwa\src\
PowerShell\src\monad\monad\src\namespaces\FileSystemProvider.cs:line 2733
   at System.Management.Automation.Provider.ContainerCmdletProvider.RemoveItem(String path, Boolean recurse, CmdletProvi
derContext context) in C:\Users\anschwa\src\PowerShell\src\monad\monad\src\namespaces\ContainerProviderBase.cs:line 422
   at System.Management.Automation.SessionStateInternal.RemoveItem(CmdletProvider providerInstance, String path, Boolean
 recurse, CmdletProviderContext context) in C:\Users\anschwa\src\PowerShell\src\monad\monad\src\engine\SessionStateConta
iner.cs:line 1152

Remove-Item is thinking the link is a directory and so failing to delete it.

If the code is changed such that File.Delete(junction) is used instead of native calls, you get:

PS C:\Users\anschwa\src\PowerShell> rm .\foobar\ -Force
Confirm
The item at C:\Users\anschwa\src\PowerShell\foobar\ has children and the Recurse parameter was not specified. If you con
tinue, all children will be removed with the item. Are you sure you want to continue?

|Y> Yes |A> Yes to All |N> No |L> No to All |S> Suspend [Default is (Y]
y
rm : Index (zero based) must be greater than or equal to zero and less than the size of the argument list.
At line:1 char:1
+ rm .\foobar\ -Force
+ ~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Remove-Item], FormatException
    + FullyQualifiedErrorId : System.FormatException,Microsoft.PowerShell.Commands.RemoveItemCommand

PS C:\Users\anschwa\src\PowerShell> $error[0].Exception.StackTrace
   at System.Text.StringBuilder.AppendFormatHelper(IFormatProvider provider, String format, ParamsArray args)
   at System.String.FormatHelper(IFormatProvider provider, String format, ParamsArray args)
   at System.String.Format(IFormatProvider provider, String format, Object arg0)
   at System.Management.Automation.Internal.StringUtil.Format(String formatSpec, Object o) in C:\Users\anschwa\src\Power
Shell\src\monad\monad\src\utils\StringUtil.cs:line 18
   at Microsoft.PowerShell.Commands.FileSystemProvider.RemoveDirectoryInfoItem(DirectoryInfo directory, Boolean recurse,
 Boolean force, Boolean rootOfRemoval) in C:\Users\anschwa\src\PowerShell\src\monad\monad\src\namespaces\FileSystemProvi
der.cs:line 2863
   at Microsoft.PowerShell.Commands.FileSystemProvider.RemoveItem(String path, Boolean recurse) in C:\Users\anschwa\src\
PowerShell\src\monad\monad\src\namespaces\FileSystemProvider.cs:line 2733
   at System.Management.Automation.Provider.ContainerCmdletProvider.RemoveItem(String path, Boolean recurse, CmdletProvi
derContext context) in C:\Users\anschwa\src\PowerShell\src\monad\monad\src\namespaces\ContainerProviderBase.cs:line 422
   at System.Management.Automation.SessionStateInternal.RemoveItem(CmdletProvider providerInstance, String path, Boolean
 recurse, CmdletProviderContext context) in C:\Users\anschwa\src\PowerShell\src\monad\monad\src\engine\SessionStateConta
iner.cs:line 1152

It fails even sooner (I think because there aren't actually any children to pass delete recursively, so it gets an empty list; just a guess).

If you use Directory.Delete(junctionPath), it works just fine!

Activity

  1. andyleejordan commented on Mar 4, 2016

    @andyleejordan
    MemberAuthor

    So, Remove-Item needs to a) not ask to recursively delete a symbolic link to a directory, and b) not recursively delete the directory, just delete the link. There's a right way to do this and a quick way to do this; as it is now, the FileSystemProvider code is all hacked up, and needs to be fixed.

    I'm going to disable the symbolic link tests for Windows until we can solve this correctly.

  2. palladia commented on Mar 4, 2016

    @palladia
    Contributor

    Problem is, sym links behave differently on Windows vs. Linux. For a symlink that points to a directory on Linux, deleting the link does not impact the directory it points to. But I believe for windows, symlinks are much closer to hard links, and deleting it will delete what the link points to.

    Do we have latest/greatest fix from CoreFx?

  3. andyleejordan commented on Apr 10, 2016

    @andyleejordan
    MemberAuthor

    George Fleming (@palladia) Can you test this out again? We have the latest and greatest .NET Core packages.

  4. andyleejordan commented on Apr 25, 2016

    @andyleejordan
    MemberAuthor

    Just FYI, this works correctly on Linux, except that it asks to remove the item recursively (even though all it does is remove the link).

  5. andyleejordan commented on Apr 28, 2016

    @andyleejordan
    MemberAuthor

    Moving this to the next milestone as we're pending ported DVT/BRT tests.

  6. 78 remaining items

  7. jszabo98 commented on Jul 28, 2019

    @jszabo98

    Looks like Windows 10 1809 can't delete profiles even through wmi. Rm -r in powershell won't work either. It looks like the MicrsoftOfficeHub app is making weird links under "AppData\Local\Packages\Microsoft.MicrosoftOfficeHub_8wekyb3d8bbwe\LocalCache". Remove-item says "is an NTFS junction point. Use the Force parameter to delete or modify this object." Remove-item -force says "There is a mismatch between the tag specified in the request and the tag present in the reparse point"

    "cmd /c rmdir /s /q" works ok.

  8. jtbrower commented on Dec 8, 2019

    @jtbrower

    Building upon what Eric Hiller (@erichiller) nicely shared, I created a PS function that uses pass-through arguments to customize the deletion of symlinks.

    Used to remove links made with mklink

    function Remove-SymLinks {
        Get-ChildItem -Force -ErrorAction Stop @Args | Where-Object { if($_.Attributes -match "ReparsePoint"){$_.Delete()} }
    }
    

    Example Usage
    Remove-SymLinks -Remove all links in the current directory
    Remove-SymlLinks -Path .\Builds -Recurse -Recursively Remove all links in the Builds Directory

    Disclaimer, I am a C# expert and a wannabe PowerShell weekend warrior so be careful with that Recurse option.

  9. francesco1119 commented on Dec 15, 2020

    @francesco1119

    FYI, I had the same problem today on PowerShell 7 and unfortunately the only way to remove the folder was through cmd /c rmdir /s /q C:\Users\Your_User_Name\Your_Folder_Name.
    Sorry to give you a bad news :(

  10. FoldZero commented on Jan 17, 2021

    @FoldZero

    If anyone stumbles across this issue as I did trying to remove reparsepoints without deleting the underlying file use

    (get-item $removethispathreparsepoint).Delete()

    Only thing that worked for me on ps7

  11. emil-prager commented on Oct 21, 2021

    @emil-prager

    In my case this error manifested only under PowerShell 5.1 (and only for ItemType SymbolicLink, i.e. no problem on ItemType Junction on 5.1).
    On PowerShell 7.1 no error was encountered when deleting the directory symlink.
    PS: The command prompt rmdir command functions ok with both symlinks and directory junctions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Committee-ReviewedPS-Committee has reviewed this and made a decisionIssue-BugIssue has been identified as a bug in the productOS-WindowsResolution-FixedThe issue is fixed.WG-Cmdletsgeneral cmdlet issues

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions