如何在返回具有相对于驱动器名称的文件时查询临时PS-Drive?

时间:2016-01-15 13:38:07

标签: powershell powershell-v4.0 network-drive

我正在尝试创建一个脚本,我将在文件服务器中搜索非继承权限。因此,我遇到了文件名的260个字符限制。我看到的一个建议,我认为会有所帮助,有几次是创建一些非持久性PS驱动器,并且可以查询这些驱动程序。

问题是,当我对新的PS Drives使用Get-ChildItem时,它使用完整的网络路径返回对象,使用我指定的名称​​而不是

# 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
}

我确信如果我用驱动器号创建了一些合适的持久性网络驱动器,我就不会遇到这个问题。

希望我没有错过,但Technet for New-PSDrive并未100%清楚这种情况。

我正在寻找一种方法来制作ps-drive并引用文件夹,同时返回相对于新驱动器名称的路径。考虑我制作的psdrive(G :)然后我的一个映射网络驱动器(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         

我知道我的确切情况存在多种解决方法,但我想了解我使用New-PSDrive显示的行为。

2 个答案:

答案 0 :(得分:7)

看起来你混合了两个不同的东西:PowerShell路径和Provider路径。 PowerShell路径在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

但是Get-Item X:\System32\notepad.exe设法创建了一个FileInfo对象,它代表了一些文件。那么,生成的FileInfo对象表示哪个文件?

(Get-Item X:\System32\notepad.exe).FullName
# C:\Windows\System32\notepad.exe

由于FileInfo对象对PowerShell驱动器X:一无所知,因此它必须存储一个路径,该路径在内部使用它可以理解的文件系统API。您可以使用Convert-Path cmdlet将PowerShell路径转换为提供程序路径:

Convert-Path X:\System32\notepad.exe
# C:\Windows\System32\notepad.exe

创建PowerShell驱动器时会发生相同的情况,该驱动器指向某个网络路径:

New-PSDrive Y FileSystem \\Computer\Share
Get-ChildItem Y:\

返回的FileInfoDirectoryInfo对象对Y:一无所知,因此他们无法拥有相对于该PowerShell驱动器的路径。内部使用的文件系统API无法理解它们。

使用-Persist选项时,情况会发生变化。在这种情况下,将创建实际映射的驱动器,这可以通过PowerShell之外的文件系统API来理解。

New-PSDrive Z FileSystem \\Computer\Share -Persist|Format-Table *Root
# Root        : Z:\
# DisplayRoot : \\Computer\Share

正如您所看到的,Root不是\\Computer\Share,而是New-PSDrive cmdlet,Z:\。由于Z:在这种情况下是真正的驱动器,FileInfoDirectoryInfo cmdlet返回的Get-ItemGet-ChildItem对象可以有相对于它的路径。

答案 1 :(得分:1)

没有经过测试,但是如果你不反对使用&这样的事可能适合你

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