8

我正在尝试编写一个批处理脚本,以获取(除其他外)计算机拥有的所有磁盘驱动器的列表。基本代码如下所示:

REM Build the list of disk drives to monitor
SETLOCAL enabledelayedexpansion
FOR /f "skip=1 tokens=1 delims=:" %%a in ('"WMIC logicaldisk WHERE drivetype=3 GET deviceid"') do (
    SET "DISK_DATABASES=!DISK_DATABASES!%%a|"
    SET "DRIVES_TO_MONITOR=!DRIVES_TO_MONITOR!%%a:\\|"
)

我很明显地构建了两个格式略有不同的列表以供以后使用。但是,当我运行它时,我得到的输出如下所示:

C|D|E||
C:\\|D:\\|E:\\|:\\|

现在,我希望在这两种情况下都有尾随管道,我可以做到这一点,但我真的很困惑为什么那里有一个额外的空白条目。如果我wmic手动运行命令,我可以看到输出的末尾确实有一个空行,但我的理解是这/f应该是专门忽略空行的。

如果我打开ECHO,看起来最后一行只是作为回车/换行或类似的形式出现。有没有办法做我所期待的?我错过了什么吗?我试图if在循环中编写一个条件来排除最后一行,但它是......时髦而且从未奏效。我感谢任何/所有帮助。

4

7 回答 7

12

我刚来这个话题。我一直在使用 findstr /v 来排除空行:

FOR /f "usebackq skip=1 tokens=1 delims=:" %%a in (`WMIC logicaldisk WHERE "drivetype=3" GET deviceid ^| findstr /v /r "^$"`) do (
于 2014-06-18T15:06:29.987 回答
5

在这种情况下,最后一次迭代产生的不是一个空项目,你得到的输出C|D|E||只有 with echo %DISK_DATABASES%
echo !DISK_DATABASES!会输出||D|E|??

那是因为最后一个元素是单个 <CR>字符。
并且<CR>字符在百分比扩展后直接删除,而不是延迟扩展。

你可以避免这种情况,使用百分比扩展来删除它们

setlocal EnableDelayedExpansion
FOR /f "skip=1 tokens=1 delims=:" %%a in ('"WMIC logicaldisk WHERE drivetype=3 GET deviceid"') do (
  set "item=%%a"
  call :removeCR

  if not "!item!"=="" (
    SET "DISK_DATABASES=!DISK_DATABASES!!item!|"
    SET "DRIVES_TO_MONITOR=!DRIVES_TO_MONITOR!!item!:\\|"
  )
)
goto :eof
:removeCR

:removeCR
set "Item=%Item%"
exit /b
于 2011-11-05T07:54:47.283 回答
4

根据http://ss64.com/nt/for_f.html

许多较新的命令和实用程序(例如 WMIC)以 unicode 格式输出文本文件,这些不能被需要 ASCII 的 FOR 命令读取。要转换文件格式,请使用 TYPE 命令。

因此,WMIC 和 FOR 似乎不能很好地结合在一起。

于 2011-11-04T23:55:33.650 回答
4

我发现了一种更有效、更可靠的方法来去除<CR>每行末尾不需要的内容。没有临时文件,也不需要 CALL。

我不明白 FOR /F 如何将 WMIC unicode 输出转换为 ASCII 的机制。通常 FOR /F 无法读取 unicode。但是无论它如何工作,每个转换后的行都以<CR><CR><LF>. FOR /F 在每个处<LF>换行,然后如果该行中的最后一个字符是<CR>最后一个<CR>,则在这种情况下留下不需要的字符<CR>

解决方案是简单地将每一行通过一个 FOR /F :-)

@echo off
setlocal enableDelayedExpansion
for /f "skip=1 delims=" %%A in (
  'wmic logicaldisk where "drivetype=3" get deviceid'
) do for /f "tokens=1 delims=:" %%B in ("%%A") do (
  set "disk_databases=!disk_databases!%%B|"
  set "drives_to_monitor=!drives_to_monitor!%%B:\\|"
)

这种方法比使用普通扩展更可靠,因为您不必担心引用或转义特殊字符。例如,使用普通扩展的 CALL 方法不能处理像"this & that" & the other. 但是这种方法对这样的字符串没有问题。

于 2013-02-02T04:59:18.880 回答
1

添加^| findstr .,你只会得到不是空行

    REM 建立要监控的磁盘驱动器列表
    SETLOCAL 启用延迟扩展
    FOR /f "skip=1 tokens=1 delims=:" %%a in (
    '"WMIC logicaldisk WHERE drivetype=3 GET deviceid" ^| findstr .') 做 (
        SET "DISK_DATABASES=!DISK_DATABASES!%%a|"
        SET "DRIVES_TO_MONITOR=!DRIVES_TO_MONITOR!%%a:\|"
    )
    

于 2017-01-11T17:37:13.087 回答
0

我处理此问题的标准习惯用法是将 WMIC 的输出写入临时文件,然后使用 TYPE(将 UTF16 简化为 ASCII)将其输入 FOR,如下所示:

:: Standard environment setup
setlocal enabledelayedexpansion
:: Every variable whose name starts with "tf" will identify a temporary
:: file - remove any such variables inherited from the parent environment
for /f %%V in ('set tf') do set %%V=
:: Create some temporary filenames. Prefix all of them with this script's
:: own name to avoid clashes with those owned by other scripts.
for /l %%I in (1,1,4) set tf%%I="%temp%\%~n0-temp%%I.txt"

:: Use temp file to work around coding mismatch between WMIC out and FOR in
wmic product where "name like 'Microsoft Office %% 2010'" get packagecache >!tf1!
for /f "skip=1" %%P in ('type !tf1!') do if exist "%%~P" msiexec /x "%%~P" /passive /norestart

:: Before quitting script, clean up temporary files
for /f %%V in ('set tf') do if exist "%%~V" del /f /q "%%~V"
endlocal
于 2013-05-19T08:55:00.600 回答
0

运行以下命令:

wmic blah /value | find "=" >> wherever

输出将是:

field=value

请注意,不会有多余的行。

于 2013-06-12T14:37:56.707 回答