批处理脚本无法处理文件名中的感叹号 !

huangapple go评论37阅读模式
英文:

Batch Script Chokes on ! Exclamation Point in Filename

问题

以下是要翻译的部分:

"The Batch file below fails to encode any .mkv file with an exclamation point (!) in the filename."

  • 下面的批处理文件无法对包含感叹号(!)的文件名的.mkv文件进行编码。

"Not sure what the problem is."

  • 不确定问题出在哪里。

"The Handbrake log complains about a "Missing output file name""

  • Handbrake日志抱怨缺少输出文件名。

"To see what is being passed as input to Handbrake when the filename (Scooby-Doo!) includes an exclamation point:"

  • 查看包含感叹号(Scooby-Doo!)的文件名传递给Handbrake时的输入:

"The output was:"

  • 输出如下:

"Using setlocal DisableDelayedExpansion before calling Handbrake corrects the input file name but the output filename is not expanded?"

  • 在调用Handbrake之前使用setlocal DisableDelayedExpansion可以修正输入文件名,但输出文件名没有展开?

"I also tried reading similar threads but I'm not sophisticated enough to understand what I'm doing wrong."

  • 我还尝试阅读类似的帖子,但我不够精通,无法理解我做错了什么。
英文:

The Batch file below fails to encode any .mkv file with an exclamation point (!) in the filename.

Not sure what the problem is.

@echo off
SETLOCAL EnableDelayedExpansion

rem <BUG>If the input .mkv filename contains a ! (exclamation mark), the script will not encode the file and continue to the next file

echo Handbrake_Encode_MKV_offPeak-beta.bat

for /r %%a in (*.mkv) do (
rem call function to pause script until electricity rates are lowest
call :sleepUtilOffPeak

rem strip parent directory from the path (set str = filename.ext)
rem set str=%%~nxa
rem strip extension from filename
rem set str=!str:~0,-4!

rem get filename and drive+path
set filename=%%~na
set drive_and_path=%%~dpa

rem echo Calling Handbrake to encode^: !str!.mp4
echo Calling Handbrake to encode^: !drive_and_path!!filename!.mp4

 	"C:\Scripts\HandBrakeCLI.exe" -v 0 --preset-import-file "C:\Scripts\Fast 1080p30-subs.json"	-Z "Fast 1080p30-subs" -i "%%a" -o "!drive_and_path!!filename!.mp4"
)
echo encoding complete. Exiting...
exit /B 0

The Handbrake log complains about a "Missing output file name"

Handbrake_Encode_MKV_offPeak-beta.bat
Day of week: 0
Hour: 14
Minute: 43
Today is a weekend
14 is not less than off-peak end : 14
14 is between 14 and 24
Going to sleep for 33420 seconds
All done sleeping. Time to work...
Calling Handbrake to encode: E:\Mamasota\Unsorted\dvds\_Encode\mkv\Scooby-Doo and Kiss Rock and Roll Mystery (2015).mp4
[00:00:13] Compile-time hardening features are enabled
[00:00:13] qsv: not available on this system
[00:00:13] vcn: not available on this system
Cannot load nvEncodeAPI64.dll
[00:00:14] hb_init: starting libhb thread
[00:00:14] thread 1 started ("libhb")
Missing output file name. Run C:\Scripts\HandBrakeCLI.exe --help for syntax.
HandBrake has exited.

To see what is being passed as input to Handbrake when the filename (Scooby-Doo!) includes an exclamation point:

echo "%%a"

The output was:

Scooby-Doodrive_and_path

Using

setlocal DisableDelayedExpansion

before calling Handbrake corrects the input file name but the output filename is not expanded?

Calling Handbrake to encode: "Scooby-Doo! & Batman The Brave and the Bold (2018).mkv" to !drive_and_path!!filename!.mp4

I also tried reading similar threads but I'm not sophisticated enough to understand what I'm doing wrong.

答案1

得分: 1

tl;dr: 将变量完全移除,只使用 %%~dpna.mp4 作为输出文件名。

当启用延迟扩展时,! 变成具有特殊含义的字符 - 它告诉解释器在执行该行时扩展变量的值,而不是在初始读取该行时扩展。如果你只是在启用延迟扩展的情况下打印 !,你可以用 ^ 转义它以正确显示。然而,由于你正在遍历文件名,无法在文件名中转义 !,因此正确处理它们的唯一方法是禁用延迟扩展。

不幸的是,由于你试图在括号内设置和使用 filenamedrive_and_path 变量,如果你希望这些变量在循环内部具有可用的值,你 必须 使用延迟扩展。这是因为在批处理中,一组括号被视为单个命令。由于你没有对这些变量进行任何字符串操作,比如获取子字符串或进行替换,你可以通过完全移除变量并在代码中使用 %%~dpna 来绕过这个限制,无论你想在代码中的什么地方使用 !drive_and_path!!filename!

英文:

tl;dr: Remove the variables entirely and just use %%~dpna.mp4 as the output filename.

<hr>

When you enable delayed expansion, ! becomes a character that has special meaning - it indicates to the interpreter that the variable should have its value expanded when the line is executed rather than when the line is initially read in. If you're simply printing a ! with delayed expansion enabled, you can escape it with a ^ so that it displays correctly. However, since you're iterating over filenames, you have no way of escaping !s in filenames so the only way to correctly process them is to disable delayed expansion.

Unfortunately, since you're trying to set and use the filename and drive_and_path variables inside of a set of parentheses, you have to use delayed expansion if you want those variables to have usable values inside of the loop. This is because a set of parentheses is read in and treated as a single command in batch. Since you aren't doing any sort of string manipulation with those variables like getting substrings or doing substitutions, you can get around this limitation by removing the variables entirely and simply using %%~dpna wherever in the code you want to use !drive_and_path!!filename!.

huangapple
  • 本文由 发表于 2023年2月14日 02:53:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/75440107.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定