windows - 如何将 Windows 批处理 for 循环的最终结果通过管道传输到另一个命令中

标签 windows batch-file for-loop

将我的脚本分成两个批处理文件,因为我不知道如何组合它:

简短以便您了解:

1.bat :使用参数调用 2.bat,对其输出进行排序并使行唯一

FOR /F ... (2.bat %1 ^| sort) DO (...)

do 部分将行相互比较并使用行缓冲区排除相同的行

2.bat:打印 FOR 循环的结果字符串

FOR ... DO ECHO

在 bash 中,这可能看起来像这样:(管道很容易)

(command) | while read line ; do echo $line ; done | sort | uniq

我真的不知道如何在Windows批处理中处理FOR循环的最终输出,以将其结果与另一个循环一起使用(不使用临时文件进行结果缓冲)

这是应用jeb解决方案的完整代码:

@echo off
setlocal EnableDelayedExpansion

REM *** This "goto" to a label, if there is one embedded in %~0 -
FOR /F "delims=: tokens=3" %%L in ("%~0") do goto :%%L

REM *** The second part calls this batch file, but embedd a label to be called
FOR /F "usebackq" %%A IN (`echo dummy ^| call %~d0\:main:\..\%~pnx0 %1 ^| SORT`) DO (
    IF NOT "%%A"=="!buff!" SET str=!str!%%A
    SET buff=%%A
)
ECHO %str:.dll=;%
endlocal
GOTO :eof

REM *** This function will be called in the pipe, but runs in batch context
:main
CD %1
:sub
FOR %%A IN (*.dll *.exe) DO dumpbin /DEPENDENTS %%A | FINDSTR /I "DLL" | FINDSTR /V "Dump :"
FOR /D %%B IN (*) DO (
    CD %%B
    CALL :sub
    CD..
)
GOTO :eof

它返回一行,其中包含文件夹 [arg1]及其所有子文件夹内所有文件的运行时依赖关系:输出字符串的 .dll 部分被剥离为适合我的需求

ADVAPI32;COMCTL32;COMDLG32;GDI32;KERNEL32;ole32;SHELL32;USER32;WININET;

这是 osx 上使用 pev 工具的对应内容:

#!/bin/sh
find "${1}" -type f \( -iname "*.dll" -o -iname "*.exe" \) | while read pe ; do
    readpe -i "${pe}" | grep -i '.dll' | awk '{print $2}'
done | sort | uniq | sed 's/.[dD][lL][lL]//g;' | tr '\n' ';' ## have the BSD sed release and can't use I with sed

最佳答案

第一步很简单

command | (
    for /f "delims=" %%L in ('more') DO @(
       echo # %%L
    )
) | sort

但是当你真的想做的不仅仅是简单的回声时,它会变得令人讨厌。
下一个代码将在 IF 1 NEQ 2

处失败
echo dummy | (
    for /f "delims=" %%L in ('more') DO @(
        echo # %%L
        if 1 NEQ 2 echo Not Equal
    ) 
)

这有不同的(复杂的)原因,您可以阅读Why does delayed expansion fail when inside a piped block of code?What happens with IF command when I pipe to it?

为了能够毫无问题地使用循环,您可以使用调用函数包装器。

@echo off
REM *** This "goto" to a label, if there is one embedded in %~0 -
FOR /F "delims=: tokens=3" %%L in ("%~0") do goto :%%L

REM *** The second part calls this batch file, but embedd a label to be called
echo dummy | call %~d0\:myFunc:\..\%~pnx0 | sort
exit /b 

REM *** This function will be called in the pipe, but runs in batch context
:myFunc
for /f "delims=" %%L in ('more') DO @(
    echo # %%L
    if 1 NEQ 2 echo Not Equal
) 
exit /b

自调用的工作原理:

call %~d0\:myFunc:\..\%~pnx0

这将扩展为批处理的完整路径,假设批处理为 C:\temp\myFile.bat 那么结果将是:
调用 C:\:myFunc:\..\temp\myFile.bat
这很奇怪,但仍然是一个有效的路径,因为 :myFunc: 不会被评估,因为 \..\ 部分将删除前面的部分。
所以批处理文件调用自身。

诀窍是, :myFunc: 仍然是 %0 变量的一部分。

FOR/F "delims=: tokens=3"%%L in ("%~0") do goto :%%L
这部分将 %0 by : 拆分为
“C”、“\”、“myFunc”和“\..\temp\myFile.bat”
并使用第三个标记 (myFunc) 来转到 %%L

这种技术的优点是,它不会破坏现有的批处理文件及其参数处理。
您也可以将该函数放入 %1 中,但是很难猜测该批处理是否应使用 %1 作为转到目标或将其用作普通参数。

关于windows - 如何将 Windows 批处理 for 循环的最终结果通过管道传输到另一个命令中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49247805/

相关文章:

windows - 使用所有参数从批处理文件调用 PowerShell 脚本

批处理数学(获胜)

python - np.mean 对于跨多列具有特定值的行

python - 如何使用for循环迭代url索引来收集数据

windows - Puppet 安装在另一个节点定义中定义的软件

windows - 如何使 Autohotkey 在启动时自动运行?

windows - 如何在 Windows 上停止 mongodb 服务器?

c - 获取簇大小

batch-file - 您可以将 .sh 文件转换为 .bat 文件吗?

python - 在 for 循环中使用迭代次数而不是列表元素