使用PowerShell Copy-Item复制匹配文件时遇驱动器找不到错误
这个问题我之前也碰到过!本质是PowerShell里对象和字符串的区别搞混了,我给你捋清楚:
问题根源
你遇到的错误完全是因为传给Copy-Item的不是纯文件路径字符串,而是带有FullName属性的自定义对象。当PowerShell尝试把这些对象转换成路径字符串时,会输出@{FullName=C:\...}这种格式——它误以为@{FullName=C是驱动器名,自然找不到对应的驱动器。
你的操作哪里错了?
大概率是在「按Name属性匹配文件」这一步,你可能用了Select-Object FullName但没加-ExpandProperty参数,导致拿到的不是路径字符串,而是包含FullName属性的对象集合。举个反例:
# 错误写法:得到的是对象,不是纯路径 $filesToCopy = Get-ChildItem "C:\Source" | Where-Object { $_.Name -like "*test*" } | Select-Object FullName
此时输出$filesToCopy会看到一堆@{FullName=C:\xxx\yyy.txt}的内容,这就是问题所在。
正确的操作步骤
1. 声明文件列表
先获取源目录下的所有文件对象:
$sourcePath = "C:\你的源目录路径" $allSourceFiles = Get-ChildItem -Path $sourcePath -File # -File确保只拿文件,排除文件夹
2. 按Name属性匹配文件
这里有两种可靠的写法:
写法一:保留FileInfo对象(推荐)
直接筛选出符合条件的文件对象,Copy-Item可以直接识别这些对象的路径:
$filesToCopy = $allSourceFiles | Where-Object { $_.Name -like "*你的匹配模式*" }
比如要匹配所有以.log结尾的文件,就写$_.Name -like "*.log"。
写法二:获取纯路径字符串
如果确实需要单独提取FullName路径,一定要加-ExpandProperty展开属性:
$filesToCopy = $allSourceFiles | Where-Object { $_.Name -like "*你的匹配模式*" } | Select-Object -ExpandProperty FullName
此时$filesToCopy就是纯字符串数组,直接用不会出问题。
3. 执行复制操作
无论用上面哪种写法,复制的正确姿势都很简单:
$targetPath = "C:\你的目标目录路径" # 写法一的对象集合可以直接传,或者用管道更简洁 $filesToCopy | Copy-Item -Destination $targetPath -Force # -Force覆盖已存在的文件
验证方法
你可以先运行$filesToCopy | Get-Member,如果看到的是FileInfo类型的成员(比如FullName、Length等),说明没问题;如果看到的是Selected.System.IO.FileInfo且只有FullName一个属性,那就是没展开属性,需要调整筛选步骤。
内容的提问来源于stack exchange,提问作者LightningWar

