Как правильно ссылаться на аргумент командного файла?
Переменная окружения source
вообще не используется в вашем командном файле. Это дополнительно определено неправильно. Лучше было бы set "source=%~1"
. Откройте командную строку , запустите call /?
и прочитайте справку по выводу от начала первой страницы до конца последней страницы.
В окне командной строки выполните следующие две команды:
echo @set source="%1">Test.bat
echo @set source>>Test.bat
Эти две командные строки создают пакетный файл Test.bat
с двумя строками:
@set source="%1"
@set source
Запустить следующее в окне командной строки:
Test.bat "Test argument 1.txt"
Вывод:
source=""Test argument 1.txt""
Видно, что случилось. Имя файла Test argument 1.txt
, переданное с необходимыми двойными кавычками из-за того, что в имени файла для пакетного файла есть пробелы, присвоенные переменной среды source
с двумя дополнительными двойными кавычками.
Следующий запуск в окне командной строки командная строка:
Test.bat "Define & See argument 1.txt"
Теперь командный процессор Windows выводит сообщение об ошибке при выполнении пакетного файла, поскольку &
не заключено в строку аргумента в двойных кавычках в первой строке после его анализа , Первая командная строка, выполняемая после анализа, теперь выглядит так:
@set source=""Define & See argument 1.txt""
Вывод справки при запуске в окне командной строки cmd /?
объясняет на последней странице, что имя файла содержит пробел или один из этих символов &()[]{}^=;!'+,`~
должен быть заключен в двойные кавычки, как это делается при вызове командного файла с необычным именем файла Define & See argument 1.txt
. Но при выполнении первой строки амперсанд больше не находится внутри строки аргумента с двойной кавычкой команды SET и по этой причине интерпретируется как оператор AND, как объяснено в ответе на одной строке с несколькими командами, использующими Windows пакетный файл .
Затем запустите следующие три командные строки в окне командной строки:
echo @if "%~1" == "" echo %~nx0 must be called with a file name!^& pause ^& goto :EOF>Test.bat
echo @set "source=%~1">>Test.bat
echo @set source>>Test.bat
Они воссоздают Test.bat
со следующим содержимым:
@if "%~1" == "" echo %~nx0 must be called with a file name!& pause & goto :EOF
@set "source=%~1"
@set source
Этот пакетный файл сначала проверяет, был ли он вызван хотя бы с одной строкой аргумента, и выводит сообщение и ждет, пока пользователь нажмет любую клавишу, чтобы убедиться, что у пользователя есть возможность прочитать его, прежде чем покинуть обработку пакетного файла с переходом к предопределенному метка конца файла. Проверьте первую строку, выполнив в окне командной строки:
Test.bat
Теперь используйте несколько раз клавишу СТРЕЛКА ВВЕРХ , чтобы вернуться из командной строки в буфер командной строки и выполнить эту строку, нажав key RETURN :
Test.bat "Define & See argument 1.txt"
На этот раз сообщение об ошибке не выводится, только строка:
source=Define & See argument 1.txt
Таким образом, видно, что этот код намного лучше не правда ли. См. Также:
Почему после использования команды 'set var = text' в командной строке не выводится строка с 'echo% var%'?
Последний запуск в окне командной строки:
del Test.bat
Теперь должно быть понятно, как ссылаться на аргументы командного файла.
Как ссылаться на имя файла, присвоенное переменной al oop с модификатором?
Запустите в окне командной строки for /?
, чтобы получить вывод справки команды Windows FOR и прочитать эту справку от начала первой страницы до конца последней страницы.
Объясняется, как обращаться к переменной l oop с помощью модификатора, например %~nI
, чтобы получить, например, только имя файла без пути и без расширения файла. %~n
ссылается на подстроку строки, назначенной в настоящее время переменной l oop между
- последним backsla sh строки, назначенной переменной l oop или начало строки, присваиваемой l oop на нём, не содержащей backsla sh вообще до
- последняя точка строки, присвоенная переменной l oop или конец строки, назначенный переменной l oop, если точка не содержит точку после последней обратной реакции / начала строки.
Итак, давайте сначала создадим командный файл со следующими четырьмя строками:
@echo off
pushd "%~dp0"
for %%I in (*.wav *.aac *.mp3) do echo %%I
popd
Этот пакетный файл выполняется из окна командной строки путем ввода его пути и имени файла с помощью клавиши TAB , как это было объяснено выводом справки при запуске cmd /?
.
. вторая командная строка помещает текущий каталог в стек и делает каталог пакетного файла текущим каталогом. Запустите в окне командной строки pushd /?
справку по этой команде. Третья командная строка ищет в этом каталоге не скрытые файлы * .wav и * .aa c и * .mp3 и присваивает имя файла без пути переменной l oop I
. Для каждой итерации l oop строка, присвоенная переменной l oop I
, просто выводится без использования модификатора. Четвертые строки извлекают ранее извлеченный путь к каталогу из стека и устанавливают этот каталог как текущий каталог для восстановления исходного текущего каталога. Запустите в командной строке окно popd /?
для получения справки по этой команде.
Затем измените третью строку в пакетном файле, чтобы получить наконец:
@echo off
pushd "%~dp0"
for %%I in (*.wav *.aac *.mp3) do echo File name of %%I is %%~nI
popd
Еще раз запустите пакетный файл из команды окно запроса, просто нажав один раз клавишу СТРЕЛКА ВВЕРХ и следующую клавишу ВОЗВРАТ .
Можно увидеть, как %%~nI
изменяет вывод строки без изменений с помощью %%I
.
Что такое конечный пакетный файл?
В вопросе не указано, какое имя файла передается в качестве аргумента в пакетный файл. Похоже, должен быть создан один видеофайл, а имя файла, передаваемое в пакетный файл, представляет собой имя файла, содержащего видеоданные, которые должны быть объединены с аудиофайлом, найденным в текущем каталоге, который может быть * .wav или *. aa c или * .mp3 file.
Итак, наконец, измените командный файл еще раз на командные строки, необходимые для этой задачи:
@echo off
if "%~1" == "" echo %~nx0 must be called with a file name!& pause & goto :EOF
pushd "%~dp0"
for %%I in (*.wav *.aac *.mp3) do ffmpeg.exe -i "%~1" -i "%%I" -c:v copy -map 0:v:0 -map 1:a:0 -shortest "%~dpn1_123.mov" & goto MovieCreated
:MovieCreated
popd
Конечно, это также возможно с несколькими аудиофайлы в каталоге пакетного файла для создания нескольких видеофайлов с видео- и аудиоданными в каталоге пакетного файла с именем каждого аудиофайла, используемого для созданного файла mov ie.
@echo off
if "%~1" == "" echo %~nx0 must be called with a file name!& pause & goto :EOF
pushd "%~dp0"
for %%I in (*.wav *.aac *.mp3) do ffmpeg.exe -i "%~1" -i "%%I" -c:v copy -map 0:v:0 -map 1:a:0 -shortest "%%~nI_123.mov"
popd
It Лучше всего указать ffmpeg.exe
с полным именем файла, т.е. диск + путь + имя файла + расширение файла, заключенное в двойные кавычки. Тогда cmd.exe
не нужно будет искать на каждой итерации l oop для ffmpeg.exe
в текущем каталоге и далее во всех каталогах переменной среды PATH
.