5
votes

I am looking for a way to get and set file attributes (hidden and readonly) in PowerShell for files where the combined path and filename are longer than 260 characters. I know that the .NET classes don't support longer file paths; I've already tried that. Attrib doesn't work either. I get error "Parameter format not correct -". Likewise Dir doesn't work either.

I am using Robocopy to obtain the filenames. Robocopy has no issues with long paths. However, I can't use Robocopy to get/set attributes since I am just using the /L list mode of Robocopy.

Anyone have workarounds for PowerShell?

Update:

subst does not support extra-long paths. It does seem to work with partial paths though.

mklink requires local volumes.

net use does not support extra-long paths. It does seem to work with partial paths though.

New-PSDrive does not support extra-long paths, not even partial paths.

2
The 260 limit is from windows I believe not .NET.Mike Cheel
Have you tried converting the filenames to 8.3 format? I have no idea if that would work or be too onerous in your environment nor if it would surmount the issue! Just a thought :)nimizen
Based on Long Paths in .NET, Part 2 of 3: Long Path Workarounds and SetFileAttributes (kernel32), I think you could write a C# dll and use the information in stackoverflow.com/questions/3666337/… to use it in PowerShell.Andrew Morton
@nimizen: That seems a little unreliable because I can't guarantee that files and paths won't have similar names. I am working with terabytes and terabytes of files.Benjamin Hubbard
@AndrewMorton: I will look into that.Benjamin Hubbard

2 Answers

1
votes

I guess using subst command to map the path as a drive letter is worth a shot. It is based on the olden days of DOS and still works on Winndows like so,

subst k: c:\some\really\complex\path\with\too\many\subdirs\and\suff\...

If subst doesn't work, try sharing a directory close to the file and access it via UNC path.

0
votes

Building on vonPryz's answer and your idea to use partial paths, the following works although it's slow and requires error suppression:

subst m: 'Insert\a\complete\path\close\to\character\limit'
sleep 1
Push-Location 'm:\rest\of\path\to\the\file' -ErrorAction SilentlyContinue
Get-ChildItem | %{
attrib $_
}
subst m: /d
sleep 1

This answer also uses SUBST to get close to where we want to be; then, Push-Location sets the long file-names' parent directory as the 'current working directory' see here. Push-Location complains about it but it works anyway insofar as Get-ChildItem and ATTRIB appear to work with this 'current working directory' rather than parsing the entire path and as a result, ATTRIB works.