我有一个我写的脚本来替换文件。我将参数传递给它以获取文件名和要搜索的基本位置。工人线是:
$SubLocations = Get-ChildItem -Path $Startlocation -Recurse -include $Filename -Force |
Where { $_.FullName.ToUpper().contains($Filter.ToUpper())}
我将 $Startlocation 设置为“C:\Users”,但是,当我尝试递归访问其他用户文件夹时,访问被拒绝。我是机器上的完全管理员,我已经尝试以管理员身份运行 powershell。我可以毫无问题地通过 Windows 资源管理器访问所有文件。有什么想法吗?
Get-ChildItem : Access to the path 'C:\Users\jepa227\Documents\My Music' is denied.
At C:\Users\krla226\Google Drive\Documents\PowerShell\Replace-File.ps1:35 char:46
+ $SubLocations = Get-ChildItem <<<< -Path $Startlocation -Recurse - include $Filename -Force |
+ CategoryInfo : PermissionDenied: (C:\Users\jepa227\Documents\My Music:String) [Get-ChildItem], Una
uthorizedAccessException
+ FullyQualifiedErrorId : DirUnauthorizedAccessError,Microsoft.PowerShell.Commands.GetChildItemCommand
更新
虽然我无法通过 GCI 让它工作,但我能够使用 WMI 来解决我的问题。有兴趣者:
$SubLocations = Get-WmiObject -Class cim_datafile -Filter "fileName = '$filename' AND Extension = '$extension'" |
Where { $_.Name.ToUpper().contains($Filter.ToUpper()) }
我能够使用以下命令在 Windows 7 机器上重现此操作,以名为“admin”的管理员用户身份登录,以提升的权限运行 powershell,并禁用 UAC:
get-childitem "c:\users\Admin\my documents"
和
cd "c:\users\admin\my documents"
get-childitem
根据文章here,我的文档、我的音乐等似乎被定义为向后兼容 pre-Vista 软件的连接点。 Powershell 本身不能很好地处理连接点。似乎这里有几个选项:
1) 从 Get-ChildItem 命令中删除 -force。这可能是您最好的选择。
get-childitem c:\users -recurse
工作无误并跳过连接点和系统目录,如 AppData。
编者注:省略
-Force
确实解决了眼前的问题,但总是跳过所有隐藏的项目,而不仅仅是导致拒绝访问错误的隐藏连接点。
2) 如果出于某种原因绝对需要使用
-Force
,您可以以编程方式递归每个子目录,跳过连接点。 这篇文章 描述了识别连接点的机制。 .ps1 脚本文件中的框架可能如下所示:
Param( [Parameter(Mandatory=$true)][string]$startLocation )
$errorActionPreference = "Stop"
function ProcessDirectory( $dir )
{
Write-Host ("Working on " + $dir.FullName)
# Work on the files in this folder here
$filesToProcess = ( gci | where { ($_.PsIsContainer -eq 0) } ) # and file matches the requested pattern
# process files
$subdirs = gci $dir.FullName -force | where {($_.Attributes -band [IO.FileAttributes]::ReparsePoint) -eq 0 -and ($_.PsIsContainer -eq 1) -and (![string]::IsNullOrEmpty($_.FullName))}
foreach( $subdir in $subdirs )
{
# Write-Host( $subdir.Name + ", " + $subdir.FullName )
if ( $subdir -ne $null )
{
ProcessDirectory -dir $subdir
}
}
}
$dirs = get-childitem $startLocation -force
$dirs | foreach { ProcessDirectory -dir $_ }
mcating的有用答案很好地解释了问题。
他建议的快速修复方法是省略
-Force
,这是可行的,因为 PowerShell ignores hidden items unless -Force
is used, and these system-defined junction points do have the Hidden
attribute (alongside the ReparsePoint
和System
属性)。
如果您确实需要
-Force
来处理一般的隐藏项目并且只想忽略这些系统定义的连接点,您可以使用Get-ChildItem
的-Attributes
参数如下:
Get-ChildItem -Force -Recurse -Attributes !Hidden, !System, !ReparsePoint
-Attributes
值 排除 具有所有以下属性集的所有项目:Hidden
、System
、ReparsePoint
,这适用于所有系统定义的连接点。PS C:\PSScripts>
Get-ChildItem -Attributes !Hidden, !System, !ResparsePoint -Recurse -Force "C:\Users\"
Get-ChildItem : Cannot bind parameter 'Attributes'. Cannot convert value "System.Object[]" to type "System.Management.Automation.FlagsExpression`1[System.IO.FileAttributes]". Error: "Unable to match the identifier name ResparsePoint to a valid enumerator name. Specify
one of the following enumerator names and try again:
ReadOnly, Hidden, System, Directory, Archive, Device, Normal, Temporary, SparseFile, ReparsePoint, Compressed, Offline, NotContentIndexed, Encrypted, IntegrityStream, NoScrubData"
At line:1 char:27
+ Get-ChildItem -Attributes !Hidden, !System, !ResparsePoint -Recurse - ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Get-ChildItem], ParameterBindingException
+ FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.PowerShell.Commands.GetChildItemCommand
您是否尝试过使用 !Hidden 等值?没想到它不接受这些值。