在 Windows 文件资源管理器下按精确长度搜索视频?

在 Windows 文件资源管理器下按精确长度搜索视频?

有没有办法在 Windows 文件资源管理器下按精确长度搜索视频?(即长度:00:31:42)

有一个命令“length:”,但它只支持“非常短、短、中、长、非常长”这样的值。

答案1

您可以搜索视频和其他媒体文件以查找特定的LengthSystem.Media.Duration),但这并不像您希望的那样简单。属性系统查看器显示Length存储为无符号 8 字节整数(Uint64电源外壳)。

姓名 价值
显示名称 长度
可见 是的
规范名称 系统.媒体.持续时间
属性键 {64440490-4C8B-11D1-8B70-080036B11A03},3
财产种类 无符号整数(8 字节)

该数字被解释为.Net系统时间跨度结构。根据文档

TimeSpan 对象的值是等于所表示时间间隔的刻度数。一个刻度等于 100 纳秒,即千万分之一秒。TimeSpan 对象的值范围可以从 TimeSpan.MinValue 到 TimeSpan.MaxValue。

电源外壳,您可以将原始值(刻度)转换为格式化的字符串,反之亦然,如下所示:

PS C:\> ([timespan]75553440000).ToString()
02:05:55.3440000
PS C:\>
PS C:\> [timespan]::Parse('02:05:55').Ticks
75550000000

虽然显示的Length以秒为单位变化,但存储的值精确到最接近的毫秒,但在显示值时它们会被截断。因此,如果你想搜索00:00:01,你实际上必须指定从00:00:01到的00:00:01.999 范围。电源外壳将实际存储的值与将显示的值反向转换为刻度后得到的值进行比较:

gci $home\videos *.avi -s | %{
    $comFolder     = $shell.NameSpace((Split-Path $_.FullName))
    $DisplayTime   = $comFolder.GetDetailsOf($comFolder.ParseName(($_.Name)) , 27)
    $Exactticks    = $comFolder.ParseName(($_.Name)).ExtendedProperty("Duration")
    $ApproxTicks   = [TimeSpan]::Parse( $DisplayTime).Ticks
    [PSCustomObject]@{
        'Display Time' = $DisplayTime
        'Exact Ticks'  = $Exactticks
        'Approx Ticks' = $ApproxTicks
        'Difference'   = $Exactticks - $ApproxTicks
}} | sort difference

输出:

Display Time  Exact Ticks Approx Ticks Difference
------------  ----------- ------------ ----------
02:43:36      98160065306  98160000000      65306
02:43:36      98160240000  98160000000     240000

   ...            ...           ...          ...

02:58:12     106929120000 106920000000    9120000
02:33:40      92209920000  92200000000    9920000

搜索条件必须以刻度表示,因此要搜索显示长度为的文件1:53:24

PS C:\> ($LowBound  = [timespan]::Parse('1:53:24').Ticks)
68040000000
PS C:\> ($HighBound = ([timespan]$LowBound).Add([timespan]::Parse('0:0:0.999')).Ticks)
68049990000
PS C:\> ($SearchExpression = 'Length:>={0} AND <= {1}' -f $LowBound , $HighBound )
Length:>=68040000000 AND <= 68049990000
PS C:\> $SearchExpression | Set-Clipboard

然后,打开探索者窗口到我的Videos文件夹,单击搜索框并按ctrl+V得到:

在此处输入图片描述

执行搜索将返回具有所需长度的视频:

在此处输入图片描述


不知道你的工作流程的细节,很难猜测如何让这一切尽可能简单。一种方法是电源外壳hh:mm:ss接受输入并执行搜索的脚本探索者

###   To keep example simple, the code assumes
###   there are no other **Explorer** windows open.

$shell        = New-Object -com shell.application
$SearchTarget = $shell.NameSpace("shell:My Video").Self.Path
$shell.Open($SearchTarget)
While ($shell.Windows().Count -eq 0) {sleep -m 25}
$TargetWin = @($shell.Windows())[0]
While ($true) {
    $SearchCriteria = Read-Host 'Enter length (hh:mm:ss)'
    $SpanTicks      = [timespan]::Parse($SearchCriteria).Ticks
    $FilterString   = 'Length:>= {0} <= {1}' -f $SpanTicks , ($SpanTicks + 9990000)
    $TargetWin.Document.FilterVIew($FilterString)
    $TargetWin.Visible = $true
}


编辑:改进的脚本:从窗口背景启动,指定范围以及特定值,以及多个值/范围。

  1. 将以下内容保存为.ps1文件。

  2. 打开电源外壳窗口并使用 dot-sourcing 运行来安装:

     . <path to .ps1 file>
    
  3. Search media by Duration现在,右键单击任何文件夹的背景即可使用。

If ($Args) {   ###   Launched from directory background context menu
    $folderPath       = $Args[0]
    $shell            = New-Object -com shell.application
    $TargetWindow     = @($shell.Windows() | where $folderPath -eq $_.Document.Folder.Self.Path  )[0]

    Function Get-Filter {
        param(
            [Parameter(Mandatory)][Uint64]$ts1,
            [Parameter(Mandatory)][Uint64]$ts2
        )
        Process {
            '(>= {0} <= {1})' -f $ts1 , ($ts2 + 9990000)
        }
    }

    $Prompt           = @"
Enter one or more (comma-separated) criteria as either:
`ta Specific TimeSpan (delimiters optional): "hh[:| |-|.]mm[:| |-|.]ss"
`tor specify a range : "<lowerTimeSpan>..<upperTimeSpan>`n`n
"@

    $SearchCriteria   = Read-Host $Prompt

    $FilterText       = 'Length: ({0})' -f (($SearchCriteria -split '\s*\,\s*' | ForEach {
        Switch -Regex ($_) {
            '^(\d{2})[\:\ \.\-]?(\d{2})[\:\ \.\-]?(\d{2})$' {
                $Ticks    = [timespan]::Parse('{0}:{1}:{2}' -f $Matches[1..3]).Ticks
                $Filter   = Get-Filter $Ticks $Ticks
            }
            '^(\d{2})[\:\ \.\-]?(\d{2})[\:\ \.\-]?(\d{2})\.\.(\d{2})[\:\ \.\-]?(\d{2})[\:\ \.\-]?(\d{2})$' {
                $Ticks1   = [timespan]::Parse(('{0}:{1}:{2}' -f $Matches[1..3])).Ticks
                $Ticks2   = [timespan]::Parse(('{0}:{1}:{2}' -f $Matches[4..6])).Ticks
                $Filter   = Get-Filter $Ticks1 $Ticks2
            }
        }
        $Filter
    }) -join ' OR ' )

    If ($FilterText) {
        $TargetWindow.Document.FilterView($FilterText)
    }
} Else {   ###   Create context menu entry
    $Key   = 'HKCU:\Software\Classes\Directory\Background\Shell\SearchMediaByDuration'
    If (!(Test-Path $key)) {
        New-Item -Path $key -Value 'Search media by &Duration'
        $PSexe   = '%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe -NoLogo -NoProfile -ExecutionPolicy Bypass'
        $splat   = @{
            'Path'       = "$key\Command"
            'Value'      = ('{0} -File {1} "%V"' -f $PSexe , $PSCommandPath)
            'ItemType'   = 'ExpandString'
        }
        New-Item @splat
    }
}

相关内容