So I know that by using this command we can loop through all the MKV / MP4 files in the current folder. But I don't want to have to Google and find out what all possible file-types or extensions the genuine Video files could have like .webm, .mkv, .mp4, .mov
etc.
Get-ChildItem -Filter *.mkv | Foreach { $_ }
I want to loop through all those regardless of the file-types or extensions, as long their kind
is Video file, by that I mean if you remember Windows folder search there's a parameter says kind:video
that lists out all videos without getting into the file extension stuff.
How can I do that with Powershell script ??
As for the interactive GUI perspective:Thanks, mclayton.
Windows Search supersedes Windows Desktop Search (WDS) v2.x; only the latter link directly shows examples such as kind:video
, but the former points to the System.Kind
documentation that implies that kind:video
and alias kind:videos
are still supported.
In practice, using these search terms in the search field of File Explorer yields image file as well as unrelated .ts
files (TypeScript files), due to an accidental name collision with the filename-extension definition at HKEY_CLASSES_ROOT\.ts
, which points to the WMP11.AssocFile.TTS
file type, which is meant for MPEG-2 TS Video files. Other such false positives are possible.
In programmatic use:
You can emulate kind:video
- i.e. a request to find all video files irrespective of their format - as follows:
# Get an array of wildcard patterns that match all filename extensions
# representing video files, e.g. @('*.3g2', ..., '*.mp4', ...)
$includePatterns =
(
Get-ItemProperty registry::HKEY_CLASSES_ROOT\.* -ErrorAction Ignore |
Where-Object PerceivedType -eq video
).PSChildName -replace '^', '*'
# Filter the target directory by those wildcard patterns.
# Note: If you're targeting the *current* directory, you can simplify to:
# Get-Item $includePatterns
# With a given path, make sure to append \*
# Add -Force to also match hidden files.
Get-Item .\* -Include $includePatterns # | ...
Note:
The above finds the filename extensions associated with video formats that are already registered locally, which may therefore not cover all known video formats; see the next section for an alternative that derives all extensions from an online source.
The local definitions, as queried above, are stored in the HKEY_CLASSES_ROOT
registry hive, where each known filename extension has its own subkey (e.g., HKEY_CLASSES_ROOT\.mp4
) whose PerceivedType
value classifies the files using that extension.
Presumably the source of the video formats used by Windows Search is the same set of registry definitions; this answer to a similar question shows programmatic use of Windows Search via its COM APIs, though a warning in a comment states that it works only with indexed locations, which would exclude networks shares and removable drives. Also, in practice, I've found kind:image
to work interactively with an indexed local folder on C:, but not with the equivalent COM API solution. Additionally, such a solution is even more complex and obscure than the registry-based one above; however, when it does work, it is noticeably faster than the registry-based solution.
-Include
supports multiple patterns as an (array) argument, separated with ,
which - unlike the single pattern supported by -Filter
- are interpreted as PowerShell wildcard patterns.[1]
The above finds video files located directly in the current directory; doing so requires use of Get-Item .\*
rather than Get-ChildItem
, unfortunately, due to the unintuitive way the -Include
parameter currently functions: see the bottom section of this answer.
To find video files in the current directory's entire subtree, replace Get-Item .\*
with Get-ChildItem . -Recurse
; -Include
does work as expected with the latter.
-ErrorAction Ignore
in the Get-ItemProperty
call is used to ignore errors that - unfortunately - may result from registry keys whose names have embedded /
characters, e.g. MAPI/IPM.Task
. These errors are the result of PowerShell by design treating both /
and \
as path separators, even though in the context of the Windows registry only \
is appropriate: see GitHub issue #5536.
Online solution, based on web scraping:
Note:
It's unclear to me whether there's an official online registry of all filename extensions representing video files; the IANA Media Types registry for videos defines media type strings, but seemingly not associated filename extensions.
The solution below relies on web scraping of https://fileinfo.com/filetypes/video
As with the GUI method and possibly also the registry-based method, there may be false positives due to name collisions; notably, as mclayton points out, the linked source lists .xml
as an extension, for file type Cinelerra Video Project
.
Therefore, you may want to implement hard-coded exclusions for such extensions.
$includePatterns =
[regex]::Matches(
(Invoke-RestMethod https://fileinfo.com/filetypes/video),
'(?<=<a href="/extension/)[^"]+'
).Value -replace '^', '*.'
Get-Item * -Include $includePatterns | Foreach { $_ }
[1] See this answer for background information.