Delete directory regardless of 260 char limit

后端 未结 17 1629
無奈伤痛
無奈伤痛 2020-12-08 02:03

I\'m writing a simple script to delete USMT migration folders after a certain amount of days:

## Server List ##
$servers = \"Delorean\",\"Adelaide\",\"Brisba         


        
相关标签:
17条回答
  • 2020-12-08 02:23

    I learnt a trick a while ago that often works to get around long file path issues. Apparently when using some Windows API's certain functions will flow through legacy code that can't handle long file names. However if you format your paths in a particular way, the legacy code is avoided. The trick that solves this problem is to reference paths using the "\\?\" prefix. It should be noted that not all API's support this but in this particular case it worked for me, see my example below:

    The following example fails:

    PS D:\> get-childitem -path "D:\System Volume Information\dfsr" -hidden
    
    
    Directory: D:\System Volume Information\dfsr
    
    
    Mode                LastWriteTime     Length Name
    ----                -------------     ------ ----
    -a-hs        10/09/2014  11:10 PM     834424 FileIDTable_2
    -a-hs        10/09/2014   8:43 PM    3211264 SimilarityTable_2
    
    PS D:\> Remove-Item -Path "D:\System Volume Information\dfsr" -recurse -force
    Remove-Item : The specified path, file name, or both are too long. The fully qualified file name must be less than 260
    characters, and the directory name must be less than 248 characters.
    At line:1 char:1
    + Remove-Item -Path "D:\System Volume Information\dfsr" -recurse -force
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : WriteError: (D:\System Volume Information\dfsr:String) [Remove-Item], PathTooLongExcepti
    on
    + FullyQualifiedErrorId : RemoveItemIOError,Microsoft.PowerShell.Commands.RemoveItemCommand
    
    PS D:\>
    

    However, prefixing the path with "\\?\" makes the command work successfully:

    PS D:\> Remove-Item -Path "\\?\D:\System Volume Information\dfsr" -recurse -force
    PS D:\> get-childitem -path "D:\System Volume Information\dfsr" -hidden
    PS D:\>
    
    0 讨论(0)
  • 2020-12-08 02:24

    Just for completeness, I have come across this a few more times and have used a combination of both 'subst' and 'New-PSDrive' to work around it in various situations.

    Not exactly a solution, but if anyone is looking for alternatives this might help.

    Subst seems very sensitive to which type of program you are using to access the files, sometimes it works and sometimes it doesn't, seems to be the same with New-PSDrive.

    0 讨论(0)
  • 2020-12-08 02:27

    I often have this issue with node projects. They nest their dependencies and once git cloned, it's difficult to delete them. A nice node utility I came across is rimraf.

    npm install rimraf -g
    rimraf <dir>
    
    0 讨论(0)
  • 2020-12-08 02:28

    If all you're doing is deleting the files, I use a function to shorten the names, then I delete.

        function ConvertTo-ShortNames{
        param ([string]$folder)
        $name = 1
        $items = Get-ChildItem -path $folder
        foreach ($item in $items){
            Rename-Item -Path $item.FullName -NewName "$name"
            if ($item.PSIsContainer){
                $parts = $item.FullName.Split("\")
                $folderPath = $parts[0]
                for ($i = 1; $i -lt $parts.Count - 1; $i++){
                    $folderPath = $folderPath + "\" + $parts[$i]
                }
                $folderPath = $folderPath + "\$name"
                ConvertTo-ShortNames $folderPath
            }
            $name++
        }
    }
    

    I know this is an old question, but I thought I would put this here in case somebody needed it.

    0 讨论(0)
  • 2020-12-08 02:29

    Any thing developed using .NET out of the box will fail with paths too long. You will have to move them to 8.3 names, PInVoke (Win32) calls, or use robocopy

    0 讨论(0)
  • 2020-12-08 02:30

    This is getting old but I recently had to work around it again. I ended up using 'subst' as it didn't require any other modules or functions be available on the PC this was running from. A little more portable.

    Basically find a spare drive letter, 'subst' the long path to that letter, then use that as the base for GCI.

    Only limitation is that the $_.fullname and other properties will report the drive letter as the root path.

    Seems to work ok:

    $location = \\path\to\long\
    $driveLetter = ls function:[d-z]: -n | ?{ !(test-path $_) } | random
    
    subst $driveLetter $location
    sleep 1
    Push-Location $driveLetter -ErrorAction SilentlyContinue
    Get-ChildItem -Recurse
    
    subst $driveLetter /D
    

    That command is obviously not to delete files but can be substituted.

    0 讨论(0)
提交回复
热议问题