如何使用通配符文件名作为命令行参数调用Windows批处理脚本

6

我有一个小的Windows批处理脚本,它只是打印出所有的命令行参数(proba.bat)。

@echo off
:loop
  if "%~1"=="" goto cont
  echo %1
  shift & goto loop
:cont

我希望这个脚本能够打印所有 .mp4 文件,如果我像这样调用它:

proba *.mp4

但实际上它只是字面打印了“*.mp4”。在Linux上这很容易,但我在这里无法让它正常工作。我做错了什么?
谢谢。

3
我的印象是dos提示符(cmd.exe)不能进行任何通配符扩展。只有一些特定的命令(如复制、目录、移动)会自行进行扩展。这样对于dos提示符来说是一件遗憾的事情,这种说法正确吗? - Daniel Barna
3
尝试使用dir %1而不是echo %1,如果你想要一个简单的列表,请使用/b。否则,请查看for命令。 - AjV Jsy
你的命令行参数是一个字符串:*.mp4,而不是文件列表。 - Stephan
1
@user3555951 是的,你说得对。除非受到保护,Unix shell 在将结果传递给命令之前会在命令行中展开通配符,而 DOS/Windows 只是按输入的参数传递(需要展开通配符的命令必须自己执行)。 - TripeHound
1个回答

2

以下是您试图执行的模拟操作:

@echo off
for %%a in ("%~1") do echo "%%a"

@ssnobody 请在评论中添加您的话 - 我不知道您在这里说什么,您的链接根本没有提到 %~1。该链接中带有波浪号的变量完全不同。ssnobody 写道:“根据 For 命令的文档,这是有效的,因为在 For 循环内部,%~1 "扩展" %1,并产生与传统通配符扩展非常相似的结果。 - foxidrive
1
你没有提到它为什么有效,只是说它有效,并且我已经解释了原因。如果你用字母I替换数字1,你会发现在文档的“变量替换”部分明确提到了它。它说:“下表列出了任何变量I的可选语法”,并指定“%~I”“扩展%I,从中删除任何周围的引号(“”)”。 - ThatOneDude
@ssnobody 你的意思是引号被移除了。是的,波浪号在"%~1"中起到了这个作用,原因是为了处理长文件名和路径以及批处理文件中的毒瘤字符。正如你在上面看到的那样,在for命令中它没有其他的功能。 - foxidrive
不,我的意思是它执行shell通配符扩展。在Linux中,您可以执行“proba *.mp4”命令,shell会将其扩展为echo <所有以mp4结尾的文件列表>。在Windows中,命令提示符没有任何通配符扩展的概念,因此“proba .mp4”将发送字面字符串“.mp4”作为参数,而不是文件列表。但是,在FOR循环中,波浪号会导致通配符扩展,我们通常希望从执行扩展的shell(例如bash)中获得扩展。 - ThatOneDude
波浪号前缀是通配符扩展的原因。不仅仅是我这么说,根据文档,%~I中的波浪号前缀表示“扩展%I”。 - ThatOneDude
1
@ssnobody - foxidrive 是正确的,但是这个想法没有被理解。CMD文档很长、复杂,而且经常隐藏,但是所有内容都在那里。A) %~1 中的 ~ 会从 %1 的值中去掉任何引号。B) "%~1" 中的引号会重新添加本地引号。这种组合确保您只有一个值上的一组引号。C) for %%a in ("%~1") 会展开 "%~1" 值中的任何通配符,然后将每个值作为 %%a 的值传递到 for 循环的主体中。 - Jesse Chisholm

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接