我是Powershell的菜鸟。我试图制作一个带有时间戳的音轨列表。
我需要的代码是读取包含mp3位置的文本文件的代码,程序将获取时间戳,例如:
考虑一个文件.txt带有以下文本:
C:\文件夹\歌曲1.mp3
C:\文件夹\歌曲1.mp3
C:\文件夹\歌曲1.mp3
程序应按时间戳打印以下内容.txt 如:
00:00:00 - 00:02:30 - 歌曲 1.mp3 00:02:30 - 00:04:32 - 歌曲 2.mp3 00:04:32 - 00:07:30 - 歌曲 3.mp3
我尝试了以下代码
$path = 'C:SanalGambitmp3'
Get-ChildItem $path -Filter *.mp3 -name | Foreach-Object {
$shell = New-Object -COMObject Shell.Application
$shellfolder = $shell.Namespace($path)
$shellfile = $shellfolder.ParseName($_)
write-host $shellfolder.GetDetailsOf($shellfile, 27) $_;
}
它只是给出了每个mp3文件的结束时间,而无需按顺序添加它们。 有人可以帮我创建一个满足我需求的程序吗?
你离:)很近
$path = 'C:SanalGambitmp3'
Get-ChildItem $path -Filter *.mp3 -name | Foreach-Object `
-Begin {
[timespan]$startTime = [timespan]::Zero
[timespan]$fullTime = [timespan]::Zero
$shell = New-Object -COMObject Shell.Application
$shellfolder = $shell.Namespace($path)
} `
-Process {
$shellfile = $shellfolder.ParseName($_)
$startTime = $fullTime
$fullTime += $shellfolder.GetDetailsOf($shellfile, 27)
"$startTime - $fullTime - $_"
}
在Begin
块中声明$shell
和$shellfolder
更加优化,因为它们不是在每个文件上定义的(这是无用的)。
除非您明确希望在控制台上显示它,否则应避免Write-Host
因为它会占用管道,因此如果要将结果存储在文件中,则文件将为空。 有了"$startTime - $fullTime - $_"
如果没有管道,它将输出,如果有管道,则传递给管道。
您可以在Process
| Out-File myResult.txt
块的右大括号 (}
) 之后添加以将其存储在文件中,或者| Tee-Object myResult.txt
如果您希望同时显示和保存它。
编辑:
如果要从仅包含文件夹的列表中获取它:
Get-Content list.txt |
ForEach {
$path = $_
Get-ChildItem -LiteralPath $path -Filter *.mp3 -Name | Foreach-Object `
-Begin {
[timespan]$startTime = [timespan]::Zero
[timespan]$fullTime = [timespan]::Zero
$shell = New-Object -COMObject Shell.Application
$shellfolder = $shell.Namespace($path)
} `
-Process {
$shellfile = $shellfolder.ParseName($_)
$startTime = $fullTime
$duration = $shellfolder.GetDetailsOf($shellfile, 27)
$fullTime += $duration
#"$startTime - $fullTime - $path$_"
[PSCustomObject]@{
Path=$path;
FileName=$_;
Duration=$duration;
StartTime=$startTime;
EndTime=$fullTime
}
}
}
正如@iRon所建议的,我已经"$startTime - $fullTime - $path$_"
注释并返回了一个PSCustomObject,如果您更喜欢第一种方法,可以将其删除(在这种情况下,不要忘记注释掉上一行)
为每个文件夹重置时间戳,如果您希望有一个整体时间戳,请移动行
[timespan]$startTime = [timespan]::Zero
[timespan]$fullTime = [timespan]::Zero
并将它们放在脚本的开头(Get-Content ...
以上),就像在第二次编辑中一样。
第二次编辑:
如果您想从包含文件夹和文件的列表中获取它:
[timespan]$startTime = [timespan]::Zero
[timespan]$fullTime = [timespan]::Zero
Get-Content list.txt |
ForEach {
$path = $_
$file = ""
if ($_ -match ".mp3$")
{
$path = $_.SubString(0, $_.LastIndexOf(''))
$file = $_.SubString($_.LastIndexOf('') + 1)
}
Get-ChildItem -LiteralPath "$path$file" -Filter *.mp3 -Name | Foreach-Object `
-Begin {
$shell = New-Object -COMObject Shell.Application
$shellfolder = $shell.Namespace($path)
} `
-Process {
$shellfile = $shellfolder.ParseName($_)
$startTime = $fullTime
$duration = $shellfolder.GetDetailsOf($shellfile, 27)
$fullTime += $duration
#"$startTime - $fullTime - $path$_"
[PSCustomObject]@{
Path=$path;
FileName=$_;
Duration=$duration;
StartTime=$startTime;
EndTime=$fullTime
}
}
}
在这种情况下,似乎只有整体时间戳是合适的。
与其使用Write-Host
(将结果输出到显示器,通常应避免),不如在管道中放置一个字符串(或[pscustomobject]
),这可以很容易地排序:
Get-ChildItem $path -Filter *.mp3 -name | Foreach-Object {
...
"$($shellfolder.GetDetailsOf($shellfile, 27)) $_"
} | Sort-Object