批处理脚本不运行,尽管其代码在 CMD 中运行

2023-12-28

我正在寻找一种简单的方法来获取以 GB 为单位的系统卷信息(批量),所以我得到了这个:

for /f "tokens=1-3" %a in ('WMIC LOGICALDISK GET FreeSpace^,Name^,Size ^|FINDSTR /I /V "Name"') do @echo wsh.echo "%b" ^& " free=" ^& FormatNumber^(cdbl^(%a^)/1024/1024/1024, 2^)^& " GiB"^& " size=" ^& FormatNumber^(cdbl^(%c^)/1024/1024/1024, 2^)^& " GiB" > %temp%\tmp.vbs & @if not "%c"=="" @echo(& @cscript //nologo %temp%\tmp.vbs >> c:\test\test2.txt | type C:\test\test2.txt

如果我只是将其复制并粘贴到 CMD 中,它就可以正常工作,但如果我从 .bat 文件运行它,它就不会执行任何操作。

我可能做错了什么?

PD:我无法使用PowerShell,我需要批量使用它。


您的代码存在以下问题:

  • 在批处理文件中,for元变量前面必须有two %- 与命令提示符中的符号相反(cmd),因此改变%a等,以%%a, ETC。;否则会出现语法错误;
  • 您可以避免过滤掉输出的标题wmic by findstr /V当使用skip=1的选项for /F;
  • 而不是财产Name我建议使用DeviceID,根据这个超级用户线程:属性有什么区别Name, Caption and DeviceID(执行时wmic LogicalDisk)? https://superuser.com/q/1074840;
  • 不确定您要查询哪些驱动器,但也许您只需要本地磁盘;如果是这样,请添加该子句where "DriveType=3";参考微软这篇文章:Win32_LogicalDisk 类 https://learn.microsoft.com/en-us/windows/desktop/CIMWin32Prov/win32-logicaldisk;
  • 临时 VBScript 脚本的创建应该发生在if调用它的条件也是为了避免无意义的文件写入活动;
  • 您在每次循环迭代中附加到文本文件,但您从未在开始时初始化空文件;也许这是故意的行为,但我不这么认为;无论如何,你可以为整个重定向一次for /F循环,或者(覆盖)写(>) 或附加 (>>), 根据你喜欢的;
  • 将管道插入type命令是没有用的,因为type无论如何都不接受任何传入数据;我猜是|符号应替换为&;尽管如此,type命令在循环中没有意义,我认为它应该在循环之后执行,而不是一次性显示完整的收集数据;
  • the echo(可以删除,因为它只是向控制台写入一个空行;
  • 最后应清除临时 VBScript 文件;

纠正所有这些事情会产生这样的批处理脚本(为了便于阅读,我不会将其全部写在一行中):

> "C:\test\test2.txt" (
    for /F "skip=1 tokens=1-3" %%a in ('
        wmic LogicalDisk where "DriveType=3" get DeviceID^,FreeSpace^,Size
    ') do @(
        if not "%%c"=="" (
            > "%TEMP%\tmp.vbs" echo WScript.Echo "%%a" ^& " free=" ^& FormatNumber^(CDbl^(%%b^) / 1024 / 1024 / 1024, 2^) ^& " GiB" ^& " size=" ^& FormatNumber^(CDbl^(%%c^) / 1024 / 1024 / 1024, 2^) ^& " GiB"
            CScript //NoLogo "%TEMP%\tmp.vbs"
        )
    )
)
type "C:\test\test2.txt"
del "%TEMP%\tmp.vbs"

不过,整个方法还可以改进:

  • 临时 VBScript 脚本可以编写一次,而不是每次编写for /F循环迭代;为此,您需要将变量值作为命令行参数传递;请参阅此线程以了解其工作原理:在 VBscript 中使用命令行参数 https://stackoverflow.com/q/2469754;
  • using echo编写临时 VBScript 文件需要大量转义,例如^&, 例如;为了避免这种情况,我们可以将 VBScript 代码放置在前缀为::::,批处理文件解释器将其视为无效的跳转标签,甚至可以通过放置exit /B就在他们面前;这个块可以很容易地被提取findstr,并且冒号可以通过删除for /F;

这就是我的意思:

> "%TEMP%\tmp.vbs" (for /F "tokens=* delims=:" %%z in ('findstr /B "::::" "%~f0"') do @echo/%%z)
> "C:\test\test2.txt" (
    for /F "skip=1 tokens=1-3" %%a in ('
        wmic LogicalDisk where "DriveType=3" get DeviceID^,FreeSpace^,Size
    ') do @(
        if not "%%c"=="" CScript //NoLogo "%TEMP%\tmp.vbs" "%%a" "%%b" "%%c"
    )
)
type "C:\test\test2.txt"
del "%TEMP%\tmp.vbs"
exit /B

::::If WScript.Arguments.Count < 3 Then WScript.Quit 1
::::WScript.Echo WScript.Arguments.Item(0) & _
::::    " free=" & FormatNumber(CDbl(WScript.Arguments.Item(1)) / 1024 / 1024 / 1024, 2) & " GiB" & _
::::    " size=" & FormatNumber(CDbl(WScript.Arguments.Item(2)) / 1024 / 1024 / 1024, 2) & " GiB"

在应用本线程中演示的技术时,您甚至可以避免使用包含 VBScript 代码的临时文件:是否可以在不使用临时文件的情况下在批处理文件中嵌入并执行 VBScript? https://stackoverflow.com/q/9074476
(另请参阅以下 Microsoft 文章:使用 Windows 脚本文件 (.wsf) https://msdn.microsoft.com/en-us/library/15x4407c.aspx, and 你们为什么不使用 .WSF 文件? https://blogs.msdn.microsoft.com/gstemp/2004/02/24/how-come-you-guys-dont-use-wsf-files/.)

<!-- :Batch script section
> "C:\test\test2.txt" (
    for /F "skip=1 tokens=1-3" %%a in ('
        wmic LogicalDisk where "DriveType=3" get DeviceID^,FreeSpace^,Size
    ') do @(
        if not "%%c"=="" CScript //NoLogo "%~f0?.wsf" "%%a" "%%b" "%%c"
    )
)
type "C:\test\test2.txt"
exit /B

---- WSF script section -->
<job><script language="VBScript">
    If WScript.Arguments.Count < 3 Then WScript.Quit 1
    WScript.Echo WScript.Arguments.Item(0) & _
        " free=" & FormatNumber(CDbl(WScript.Arguments.Item(1)) / 1024 / 1024 / 1024, 2) & " GiB" & _
        " size=" & FormatNumber(CDbl(WScript.Arguments.Item(2)) / 1024 / 1024 / 1024, 2) & " GiB"
</script></job>

这是另一种不使用临时 VBScript 文件的方法,应用此线程中说明的方法:HTA 和批处理混合,从 BATCH 部分传递变量 https://stackoverflow.com/q/43105028。这样做的缺点是 HTA 窗口的出现和消失会短暂闪烁。
(另请参阅这篇 Microsoft 文章:HTML 应用程序 (HTA) https://blogs.msdn.microsoft.com/noahc/2007/03/26/html-applications-htas/.)

<!-- ::Batch script section ----
> "C:\test\test2.txt" (
    for /F "skip=1 tokens=1-3" %%a in ('
        wmic LogicalDisk where "DriveType=3" get DeviceID^,FreeSpace^,Size
    ') do @(
        if not "%%c"=="" set "DeviceID=%%a" & set "FreeSpace=%%b" & set "Size=%%c" & MSHTA "%~f0"
    )
)
type "C:\test\test2.txt"
exit /B

---- ::HTA script section -->
<script language="VBScript">
    Set Env = CreateObject("WScript.Shell").Environment("Process")
    Set StdOut = CreateObject("Scripting.FileSystemObject").GetStandardStream(1)
    If Not Env("DeviceID") = "" Then
        StdOut.WriteLine(Env("DeviceID") & _
            " free=" & FormatNumber(CDbl(Env("FreeSpace")) / 1024 / 1024 / 1024, 2) & " GiB" & _
            " size=" & FormatNumber(CDbl(Env("Size")) / 1024 / 1024 / 1024, 2) & " GiB")
    End If
    Set StdOut = Nothing
    Set Env = Nothing
    Close()
</script>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

批处理脚本不运行,尽管其代码在 CMD 中运行 的相关文章

  • 将目录添加到path环境变量

    我的要求是将目录之一添加到path安装我的应用程序时 Windows 中的环境变量并将其删除path使用批处理文件卸载时的环境变量 在与此相关的 stackoverflow 答案之一中 建议将目录添加到路径环境变量中 setx path C
  • 以不可见模式运行主bat文件

    我有一个大师 bat文件有 call file1 bat call file2 bat call file3 bat call file4 bat 我想在我的 Windows Server 2008 上安排它以静默 不可见模式运行 我正在寻
  • 找不到图标路径的 Cordova Android 版本

    打字时cordova build android在 DOS 框中 没有构建任何内容 但我看到一条错误消息 错误 源路径不存在 resources android icon drawable hdpi icon png 我已经更新了 Cord
  • 如何使用批处理文件实现快速排序?

    虽然通常情况下 为工作选择正确的语言是件好事 但有时尝试用一种非常不合适的语言做一些事情可能会很有启发 它可以帮助您更好地理解问题 也许你不知道have按照您认为的方式解决它 它可以帮助您更好地理解该语言 也许它支持的功能比您想象的还要多
  • 使用 psexec 远程执行时,脚本中的 Reg 查询不起作用

    我最近得到了一个脚本 用于查询 reg 的临时文件夹路径并清理该文件夹 它工作得很好 感谢 Compo 但是当与 psexec 远程使用时 它说 系统无法找到指定的注册表项或值 在使用 PSEXEC 执行批处理之前 我首先将其复制到 C 然
  • 如何使用批处理文件将多个命令插入到批处理文件中

    我正在制作一个批处理文件 我们称之为 Create bat 它将创建一个批处理文件 我们称之为 Created bat 该文件将在其中插入多个命令 其中一条命令如下 FOR F x IN tasklist NH FI IMAGENAME e
  • 找到第一个命中后停止 DIR 命令搜索

    在 CMD EXE 中我可以使用以下命令搜索某些内容DIR 以下面的例子为例 DIR C EXCEL EXE A D B S 虽然需要一段时间才能看清C 盘的整个结构 但是第一次匹配还是比较快的 Q 有没有办法自动地一旦发现命中 就停止命令
  • “调用”C:\Program Files\nodejs\\node.exe”错误

    我一直在尝试安装节点js并安装浏览器同步 C Users Aly gt npm install g browser sync CALL C Program Files x86 nodejs node exe C Program Files
  • 使用 set /p 更新批处理脚本的变量始终包含最后一个值

    我正在尝试使用 set p 命令在循环内调整 Windows 批处理变量 键盘输入后 变量仍然包含旧值 我读到通过 set p 设置的变量仅具有本地范围 但我不明白 本地 在这里的真正含义 echo off setlocal EnableD
  • 如何让批处理文件等待另一个批处理文件完成执行?

    如何让一个批处理文件等待另一个批处理文件完成 例如 我有 echo hi gt r txt echo some piece of code gt gt r txt start ar bat echo some piece of code g
  • 如何获取%CD%的父路径

    如何获取当前 CD 的父路径 例如 ECHO CD result C Windows System32 这不起作用 ECHO CD 期望的结果 C Windows 尝试更改当前目录 然后使用 cd pushd echo cd popd
  • CMD shell 中的可用空间

    有没有办法在 CMD 中获取磁盘或文件夹的可用磁盘空间量 无需安装一些第三方应用程序 我有一个 CMD 可以将一个大文件复制到给定目录 当然可以使用 复制命令返回错误级别 但我必须等待时间 需要复制文件 例如 然后磁盘已满并且复制操作失败
  • powershell 和 cmd 之间的文件大小不同[重复]

    这个问题在这里已经有答案了 我正在使用一点processconf js工具来构建configuration json来自多个文件 json files 这是我正在使用的命令 node processconf js file1 json fi
  • 打开 PDF 到书签/指定目标?

    我正在尝试使用 python 打开特定书签的 PDF 到目前为止 我可以在命令提示符中运行以下命令并得到我想要的 last是 PDF test pdf 中指定目的地的名称 C Program Files x86 Adobe Reader 1
  • 最后一个参数中的正斜杠会导致批处理文件目录(“%~dp0”)的路径发生更改

    我正在学习如何在批处理脚本中使用参数 并最终创建了某种用于读取参数和设置参数的模板 echo off SetLocal EnableDelayedExpansion set needextra set errstat set noflag
  • for循环批处理文件内的算术

    我在批处理文件中有一个 for 循环 如下所示 for y in 100 200 300 400 500 do set a x y 25 echo x 该行 set a x y 25 好像没有做任何划分 将每个 y 除以 25 的正确语法是
  • 如何使用Windows批处理命令删除“无扩展名的文件”的所有内容

    我想删除以 FIlE 为扩展名的文件的内容 即没有扩展名 我知道如何删除文本文件的内容 但不知道如何删除以 文件 为扩展名的文件 我会感谢你的努力 提前致谢 Use Del 在批处理文件中删除没有扩展名的文件 use Dir A D 列出所
  • 访问另一个批处理文件中的批处理函数

    好吧 假设我们有一个名为 lib cmd 的文件 它包含 echo off GOTO EXIT FUNCTION echo something GOTO EOF EXIT exit b 然后我们有一个名为 init cmd 的文件 它包含
  • 如何在批处理文件中回显换行符?

    如何从批处理文件输出中插入换行符 我想做类似的事情 echo hello nworld 这会输出 hello world Use echo hello echo echo world
  • 更改 Wi-Fi 配置文件的密码

    在我志愿服务的长期护理医院中 每个月的第一天 访客 Wi Fi 连接的密码都会更改 这给工作人员带来了大量的工作 也给患者带来了很多挫败感 其中许多人的行动能力非常有限 是的 真正的解决方案是让 IT 团队保留相同的密码 但这不会发生 大多

随机推荐