Преобразование строки cmd в powershell - PullRequest
1 голос
/ 26 марта 2020

РЕДАКТИРОВАТЬ 2: окончательный код ниже

Мне нужна помощь по преобразованию некоторых кодов, так как я новичок в 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;

1 Ответ

2 голосов
/ 26 марта 2020
$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 должен быть найден в $SourceFolder и тоже, а путь к выходному файлу, переданный в -o, должен также иметь префикс $SourceFolder, что достигается с помощью расширяемых строк ("...").

Основные моменты для рассмотрения:

  • for %%f in (*.mkv) не имеет прямого аналога в PowerShell; вместо этого вы правильно использовали Get-ChildItem, чтобы получить список подходящих файлов, которые возвращаются как System.IO.FileInfo экземпляров.

    • Однако -Include не будет работать должным образом при отсутствии -Recurse (если вы не добавите \* - см. , эта проблема GitHub ; -Filter работает, а также является более быстрым методом, но имеет свои ограничения и устаревшие причуды (см. этот ответ ).
  • В то время как PowerShell также позволяет выполнять команды, имена или пути которых хранятся в переменной (или указан как заключенный в кавычки строковый литерал), вам потребуется &, оператор вызова , чтобы вызвать его, по причинам syntacti c.

  • Внутри блока сценария ({ ... }), переданного командлету ForEach-Object, automati c переменная $_ представляет входной объект конвейера под рукой.

    • $_.FullName гарантирует, что входные экземпляры System.IO.FileInfo представлены их полным путем, когда мы редактирование в строковом контексте.

    • Этот дополнительный шаг больше не требуется в PowerShell [Core] 6+, где System.IO.FileInfo экземпляры, к счастью всегда , преобразуют как их полные paths.

  • Символу @ предшествует ` (обратный удар), escape-символ PowerShell, поскольку @ - в отличие от cmd - является метасимволом , то есть символом со специальным значением синтаксиса c. `@ гарантирует, что @ будет обработан дословно и, следовательно, передан в mkvmerge.

    • В качестве альтернативы, вы можете указать в кавычках аргумент вместо экранирования только @: "@$optionsFile"

    • См. этот ответ для справочной информации.

  • Как правило, не необходимо заключать аргументы в "..." в PowerShell, даже если они содержат пробелы или другие метасимволы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...