I am trying to create a script where I will be searching the file servers for non inherited permissions. I have run into the 260 character limit for file names as a result. A suggestion I saw, that I thought would help, a couple of times was to create some non persistent PS Drives a couple of levels deep and query those.
Problem is when I use Get-ChildItem
against the new PS Drives it is returning object with the full network path and not using the name I assigned it.
# Cycle the folders
Get-ChildItem $rootPath -Directory | select -first 1 | ForEach-Object{
$target = $_
# Create a PS Drive for each sub directory and get all the folders
[void](New-PSDrive -Name $target.Name -PSProvider FileSystem $target.FullName)
# Get the file objects.
Get-ChildItem "$($target.Name):\" -Recurse
}
I am sure that if I created some proper persistent network drives with a drive letter I would not have this issue.
Hopefully I just didn't miss it but Technet for New-PSDrive was not 100% clear about this scenario.
I am looking for a way to make ps-drive and reference there folders while returning paths relative to the new drive name. Consider the output from a psdrive I made (G:) then one of my mapped network drives (M:).
PS M:\> Get-ChildItem G:\
Directory: \\server01\COMMON\Folder
Mode LastWriteTime Length Name
---- ------------- ------ ----
d---- 6/18/2011 8:14 AM Folder 1
d---- 6/18/2011 8:14 AM Folder 2
PS M:\> Get-ChildItem M:\
Directory: M:\
Mode LastWriteTime Length Name
---- ------------- ------ ----
d---- 5/8/2015 11:00 AM Backup
d---- 5/8/2015 11:00 AM covers
d---- 5/8/2015 11:00 AM drop
d---- 5/8/2015 11:00 AM Expense
I am aware that multiple workarounds exists for my exact situation but I would like to understand the behavior that I am showing with New-PSDrive
.
The Get-PSDrive cmdlet gets the drives in the current session. You can get a particular drive or all drives in the session. This cmdlet gets the following types of drives: Windows logical drives on the computer, including drives mapped to network shares.
Windows PowerShell uses the noun, PSDrive, for commands that work with Windows PowerShell drives. For a list of the Windows PowerShell drives in your Windows PowerShell session, use the Get-PSDrive cmdlet.
Although we can use Net Use in PowerShell, there is a more powerful alternative, the New-PSDrive cmdlet. With the New-PSDrive cmdlet, we cannot only map network drives but also create drive mappings to local folders or registry keys on our computer.
Looks like you are mixing up two different things: PowerShell path and Provider path. PowerShell paths are not visible outside of PowerShell.
New-PSDrive X FileSystem C:\Windows
(Get-Item X:\System32\notepad.exe).get_Length() #OK
([IO.FileInfo]'X:\System32\notepad.exe').get_Length() #Error
But Get-Item X:\System32\notepad.exe
managed to create a FileInfo
object, which represents some file. So, what file is represented by the resulting FileInfo
object?
(Get-Item X:\System32\notepad.exe).FullName
# C:\Windows\System32\notepad.exe
Since the FileInfo
object knows nothing about PowerShell drive X:
, it has to store a path, which internally uses the file system API which it can understand. You can use Convert-Path
cmdlet to convert PowerShell path to Provider path:
Convert-Path X:\System32\notepad.exe
# C:\Windows\System32\notepad.exe
Same happens when you create the PowerShell drive, which point to some network path:
New-PSDrive Y FileSystem \\Computer\Share
Get-ChildItem Y:\
Returned FileInfo
and DirectoryInfo
objects know nothing about Y:
, so they can not have paths relative to that PowerShell drive. Internally used file system API will not understand them.
Things changes when you use the -Persist
option. In that case real mapped drives will be created, which can be understood by file system API outside of PowerShell.
New-PSDrive Z FileSystem \\Computer\Share -Persist|Format-Table *Root
# Root : Z:\
# DisplayRoot : \\Computer\Share
As you can see, the Root
will be not \\Computer\Share
as you ask in New-PSDrive
cmdlet, but Z:\
. Since Z:
is a real drive in this case, FileInfo
and DirectoryInfo
objects returned by Get-Item
or Get-ChildItem
cmdlet can have paths relative to it.
haven't tested, but if you're not opposed to using 'subst' something like this might work for you
function Get-FreeDriveLetter {
$drives = [io.driveinfo]::getdrives() | % {$_.name[0]}
$alpha = 65..90 | % { [char]$_ }
$avail = diff $drives $alpha | select -ExpandProperty inputobject
$drive = $avail[0] + ':'
$drive
}
$file = gi 'C:\temp\file.txt'
$fullname = $file.FullName
if ($fullname.length -gt 240) {
$drive = Get-FreeDriveLetter
$path = Split-Path $fullname
subst $drive $path
$subst = $true
rv path
$fullname = Join-Path $drive $(Split-Path $fullname -Leaf)
}
$fullname
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With