我有一个经常使用的脚本来获取文件列表,然后用 ffmpeg 处理它们,其开头如下:
$files = Get-ChildItem -Path "Season *\*" -Include *.mp4, *.mkv, *.m4v, *.avi, *.wmv, *.mpg -recurse
ForEach ($file in $files) {
$parent = Split-Path $file -parent
$origFile = $parent+'\'+$file.name
$shortName = $file.name
....
我需要一个解决方案,以便能够在更灵活的目录中使用它,但避免目录中的连接(递归命令将永远沿着连接行进)。我在超级用户上找到了答案,关联。我将原始脚本包装在一个函数中,并修改了此处找到的递归函数的第 4 行,以调用该函数并处理找到的文件。
function Recurse($path) {
$fc = new-object -com scripting.filesystemobject
$folder = $fc.getfolder($path)
foreach ($i in $folder.files) {if ($i.name -match '.*\.(mp4|mkv|m4v|avi|wmv|mpg)$') {processFile($i)}}
foreach ($i in $folder.subfolders) {
$i | select Path
if ( (get-item $i.path).Attributes.ToString().Contains("ReparsePoint") -eq $false) {
Recurse($i.path)
}
}
}
function processFile($file) {
$parent = Split-Path $file -parent
$origFile = $parent+'\'+$file.name
$shortName = $file.name
...
但是,很明显,递归函数的操作和生成列表的方式不会创建与 get-childitem 相同类型的文件对象(?)。像“Split-Path $file -parent”这样的操作现在不起作用,而是什么也不返回。我测试过的所有系统都表明变量 $file 是一个 System._ComObject,我假设它是在递归函数的第一个命令中设置的。这不就是 Get-Childitem 返回的吗?我如何让这两个函数一起工作?
我愿意修改原始脚本或递归函数,以便原始功能(例如调用 Split-Path)再次发挥作用。
答案1
System._ComObject,我假设它是在递归函数的第一个命令中设置的。这不就是 Get-Childitem 返回的内容吗?
否。从脚本.文件系统对象是不同类型的对象,那么你从Powershell 文件系统提供程序。Powershell 提供程序基本上由 .NET 组成系统.IO.文件信息对象。虽然它们看起来可能相同,但由于它们都处理文件系统操作,因此这两种类型的对象并不兼容。
微软确实提供了一份文档建议转换。
实际上,您的脚本已经使用一种方法来转换它们,在您的一个 if 条件中。您执行 的部分get-item $i.path
。该代码片段基本上将一种类型的对象转换为另一种类型的对象。它返回Get-Item
一个 powershell 文件系统对象,为此,您为 Get-Item 命令提供由 中的 scripting.filesystemobject 值返回的完整路径$i
。您也可以在其他地方使用同样的技巧。