powershell - 将一行cmd转换为powershell
问题描述
EDIT2:下面的最终代码
我在转换一些代码方面需要帮助,因为我对 mkvmerge、powershell 和命令提示符非常陌生。
CMD 代码来自https://github.com/Serede/mkvtoolnix-batch/blob/master/mkvtoolnix-batch.bat
for %%f in (*.mkv) do %mkvmerge% @options.json -o "mkvmerge_out/%%f" "%%f"
到目前为止我所管理的
$SourceFolder = "C:\tmp" #In my actual code, this is done using folder browser
$SourceFiles = Get-ChildItem -LiteralPath $SourceFolder -File -Include *.mkv
$SourceFiles | foreach
{
start-process "F:\Desktop\@progs\mkvtoolnix\mkvmerge.exe"
}
我将不胜感激任何帮助,因为我在学习双方时无法理解和转换。非常感谢你。
**编辑 2:**这是我的最终工作代码。
Function Get-Folder($initialDirectory) {
#Prompt to choose source folder
[void] [System.Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms')
$FolderBrowserDialog = New-Object System.Windows.Forms.FolderBrowserDialog
$FolderBrowserDialog.Description = 'Choose the video folder'
$FolderBrowserDialog.RootFolder = 'MyComputer'
if ($initialDirectory) { $FolderBrowserDialog.SelectedPath = $initialDirectory }
[void] $FolderBrowserDialog.ShowDialog()
return $FolderBrowserDialog.SelectedPath
}
Function ExitMessage
{
#endregion Function output
Write-Host "`nOperation complete";
Write-Host -NoNewLine 'Press any key to continue...';
$null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown');
Exit;
}
($SourceFolder = Get-Folder | select )
#Check for output folder and create if unavailable
$TestFile = "$SourceFolder" + "\mkvmerge_out"
if ((Test-Path -LiteralPath $TestFile) -like "False")
{
new-item -Path $SourceFolder -name "mkvmerge_out" -type directory
Write-Host 'Folder created';
}
#Checking for the presence of a Json file
$TestFile = (Get-ChildItem -LiteralPath $SourceFolder -File -Filter *.json)
if ($TestFile.count -eq 0)
{
Write-Host 'json file not found';
ExitMessage;
}
$TestFile = "$SourceFolder" + "\$TestFile"
#Getting the total number of files and start timer.
[Int] $TotalFiles = 0;
[Int] $FilesDone = 0;
$TotalFiles = (Get-ChildItem -LiteralPath $SourceFolder -File -Filter *.mkv).count
$PercentFiles = 0;
$Time = [System.Diagnostics.Stopwatch]::StartNew()
#Start mkvmerge process with progress bar
$mkvmergeExe = 'F:\Desktop\@progs\mkvtoolnix\mkvmerge.exe'
$JsonFile = "$TestFile" # alternatively, use Join-Path
Get-ChildItem -LiteralPath $SourceFolder -File -Filter *.mkv | ForEach-Object {
$PercentFiles = [math]::truncate(($FilesDone/$TotalFiles)*100)
Write-Progress -Activity mkvmerge -Status ("{0}% Completed; {1}/{2} done; Time Elapsed: {3:d2}:{4:d2}:{5:d2}" -f $PercentFiles, $FilesDone, $TotalFiles, $Time.Elapsed.Hours, $Time.Elapsed.minutes, $Time.Elapsed.seconds) -PercentComplete $PercentFiles;
Write-Host "Processing $_"
$f = $_.FullName
$of = "$SourceFolder\mkvmerge_out\$($_.Name)"
& $mkvmergeExe -q `@$JsonFile -o $of $f
$FilesDone++
}
Remove-Item -LiteralPath $JsonFile #Remove this line if you want to keep the Json file
$PercentFiles = [math]::truncate(($FilesDone/$TotalFiles)*100)
Write-Progress -Activity mkvmerge -Status ("{0}% Completed; {1}/{2} done; Time Elapsed: {3:d2}:{4:d2}:{5:d2}" -f $PercentFiles, $FilesDone, $TotalFiles, $Time.Elapsed.Hours, $Time.Elapsed.minutes, $Time.Elapsed.seconds) -PercentComplete $PercentFiles;
ExitMessage;
解决方案
$mkvmergeExe = 'F:\Desktop\@progs\mkvtoolnix\mkvmerge.exe'
$optionsFile = "$SourceFolder\options.json" # alternatively, use Join-Path
Get-ChildItem -LiteralPath $SourceFolder -File -Filter *.mkv | ForEach-Object {
$f = $_.FullName
$of = "$SourceFolder\mkvmerge_out\$($_.Name)"
& $mkvmergeExe `@$optionsFile -o $of $f
}
请注意,您的cmd
代码假定它在当前目录中运行,而您的 PowerShell 代码通过$SourceFolder
;显式传递一个目录。因此,该options.json
文件也必须在 in 中查找$SourceFolder
,并且传递给的输出文件路径-o
必须以$SourceFolder
too 为前缀,这是通过可扩展字符串( "..."
) 实现的。
需要考虑的要点:
for %%f in (*.mkv)
在 PowerShell 中没有直接对应物;相反,您正确地使用Get-ChildItem
了获取匹配文件的列表,这些文件作为System.IO.FileInfo
实例返回。- 但是,
-Include
如果没有-Recurse
(除非您附加\*
- 请参阅此 GitHub 问题;-Filter
确实,并且也是更快的方法,但它有其局限性和遗留怪癖(请参阅此答案)。
- 但是,
虽然 PowerShell 也允许您执行名称或路径存储在变量中(或指定为带引号的字符串文字)的命令,但出于句法原因,您需要
&
调用运算符 来调用它。在传递给cmdlet的脚本块( ) 中,自动变量表示手头的管道输入对象。
{ ... }
ForEach-Object
$_
$_.FullName
确保System.IO.FileInfo
输入实例在字符串上下文中使用时由其完整路径表示。在 PowerShell [Core] 6+ 中不再需要这个额外的步骤,
System.IO.FileInfo
幸好实例总是字符串化为它们的完整路径。
该
@
字符前面是`
(backtick),PowerShell 的转义字符,因为@
- 与 in 不同cmd
- 是一个元字符,即具有特殊句法含义的字符。`@
确保 the@
被逐字处理,因此传递给mkvmerge
.或者,您可以引用参数而不是仅转义
@
:"@$optionsFile"
有关背景信息,请参阅此答案。
通常不需要在PowerShell中包含参数
"..."
,即使它们包含空格或其他元字符。
推荐阅读
- apache-spark - 使用 python 可执行文件而不是 spark-submit 提交 Spark 作业
- apache-spark - 在pyspark中使用array_zip进行groupby和collect_list时保留列名
- ruby - 检查两个字符串是否非常相似(相似的字符、模式等)
- android - (RoomDatabase) 从资产更新数据库值而不丢失用户数据
- javascript - 使用 Vue.js,如何在 v-for 循环中使用模态组件?
- javascript - 如何使用 document.createElement("img") 在 javascript 中显示带有类的 img?
- mysql - 如何避免我的 Express API 被公司防火墙阻止
- c# - 通过 DBContext .Net Core 的 OnModelCreating 存储自定义类属性,如 String
- mysql - 使用 SQL 清理列中的数据
- yubikey - 如何解码 Yubikey OTP 令牌?