批处理文件:转义!在For Loop中

时间:2017-04-16 04:34:38

标签: batch-file for-loop cmd escaping

我正在尝试创建一个for循环,它将通过一个目录并对该目录中的所有文件运行ffmpeg命令。我的问题是,某些文件名称中包含bar,这会导致使用延迟扩展时出现问题。我研究了很多解决方案,但没有一个能让我到任何地方。目前我可以回复包含!的文件名,但我似乎无法将带有!的文件名传递到我的for循环中,因为延迟扩展会有效地删除!

这是我的批处理脚本:

!

这适用于名称中没有@echo off setlocal enabledelayedexpansion for %%f in ("Y:\Samples\Test Videos\*.mkv") do ( set "filename=%%~nxf" ffmpeg -i "%%f" -vcodec copy -acodec copy -scodec copy -vbsf h264_changesps=level=40 -vbsf h264_changesps=fps=24000:1001 "E:\Converted\!filename!" ) pause 的所有文件。如果我使用这样的批处理脚本:

!

然后我可以使用包含的@echo off for %%f in ("Y:\Samples\Test Videos\*.mkv") do ( call :command "%%f" ) pause :command set "fname=%~nx1" set "fpath=%~dpnx1" echo %fname% ffmpeg -i %fpath% -vcodec copy -acodec copy -scodec copy -vbsf h264_changesps=level=40 -vbsf h264_changesps=fps=24000:1001 "E:\Converted\%fname%" 来获取文件名和完整路径以回显,但引用!%fname%的ffmpeg命令会返回%fpath%消息。如果我在回显关闭后添加No such file or directory并将ffmpeg字符串更改为SetLocal EnableDelayedExpansion而不是!,那么我再次收到%消息。

我知道在No such file or directory循环中,语句的FOR部分中的所有内容都会扩展到其他所有内容之前,这就是我需要使用延迟扩展的原因,但是如何使用它仍然可以使用包含DO的文件名?有没有办法让第一批接受名称中包含!的文件?

3 个答案:

答案 0 :(得分:5)

最简单的解决方案是不使用延迟扩展。

@echo off
    setlocal enableextensions disabledelayedexpansion
    set ffmpegArguments=-vcodec copy -acodec copy -scodec copy -vbsf h264_changesps=level=40 -vbsf h264_changesps=fps=24000:1001

    for %%f in ("Y:\Samples\Test Videos\*.mkv") do (
        ffmpeg -i "%%f" %ffmpegArguments% "E:\Converted\%%~nxf" 
    )
    pause

无需将从for可替换参数中检索到的信息分配给变量,只需使用检索到的值

答案 1 :(得分:0)

:command

SETLOCAL DISABLEDELAYEDEXPANSION

set "fname=%~nx1"
set "fpath=%~dpnx1"
echo %fname%
ffmpeg -i %fpath% -vcodec copy -acodec copy -scodec copy -vbsf h264_changesps=level=40 -vbsf h264_changesps=fps=24000:1001 "E:\Converted\%fname%"

ENDLOCAL
GOTO :EOF

应该通过在!是文字字符时禁用delayedexpansion来解决您的问题。

我添加了goto的习惯,所以如果我添加一个新的子程序,我就不必记住它。

答案 2 :(得分:0)

我发布太快了!我终于搞定了!

事实证明,在ffmpeg输入中使用%fpath%的第二个脚本只获取文件路径,直到它被截断的第一个空格(因为我没有用引号括起来)。将%fpath%放入引号后,该脚本将使用名称中包含!的文件!这是:

@echo off
for %%f in ("Y:\Samples\Test Videos\*.mkv") do (
   call :command "%%f"
)

:command
set "fname=%~nx1"
set "fpath=%~dpnx1"
ffmpeg -i "%fpath%" -vcodec copy -acodec copy -scodec copy -vbsf h264_changesps=level=40 -vbsf h264_changesps=fps=24000:1001 "E:\Converted\%fname%"