考虑 Windows 命令外壳 cmd.exe 中的管道:
C:\>feed | filter
Run Code Online (Sandbox Code Playgroud)
馈送过程的标准输出似乎直到馈送过程运行完成后才能达到过滤过程的标准输入。
这种类型的“缓冲”可能会导致长时间运行的馈送过程的输出消息出现烦人的延迟(您可能希望在早期失败时按“ctrl-c”来中断它)。
有没有办法避免这种情况,以便一旦数据可用,馈送过程的标准输出就达到过滤过程的标准输入?(无缓冲)
例如,以下简化示例:
feed.bat:
@echo off
echo something
sleep 3
echo something else
Run Code Online (Sandbox Code Playgroud)
过滤器.bat:
@echo off
for /F "tokens=*" %%a in ('more') do (
echo _%%a
)
Run Code Online (Sandbox Code Playgroud)
以下命令直到 3 秒后(睡眠完成时)才显示任何内容:
C:\>feed | filter
_something
_something else
Run Code Online (Sandbox Code Playgroud)
所需的行为是打印 '_something',然后延迟 3 秒,然后打印 '_something else'。
more我喜欢使用括号中的命令块,因为它允许我立即将块中所有命令的输出通过管道传输到(或任何其他命令)。
通常,我也可以在这些块内添加注释(rem)。
但是,我似乎无法将这两个功能结合起来:带有注释的块more(或任何其他命令)根本不被执行。这是为什么?能解决吗?
@echo off
rem This works (prints X1)
(
echo X1
)
rem This works (prints X2)
(
echo X2
) | more
rem This works (prints X3)
(
rem
echo X3
)
rem Why does this print nothing?
(
rem
echo X4
) | more
rem Or this?
(
echo X4
rem
) | more
rem This works (prints X5)
(
:: Using colons instead of rem
echo X5
) | more
Run Code Online (Sandbox Code Playgroud) 我有一个包含一些功能的批处理文件.每个函数都使用setlocal它的变量不会污染主批处理脚本.我注意到我ENABLEDELAYEDEXPANSION在主批处理脚本中第一次只需要参数,而不是每个嵌套的setlocal.例如:
@echo off
setlocal ENABLEDELAYEDEXPANSION
set VAR=hi
CALL :function
echo bye
exit /b 0
:function
setlocal
echo !VAR!
exit /b 0
Run Code Online (Sandbox Code Playgroud)
这是否允许在批处理文件中,因为除非如下所述,否则我无法找到它.这setlocal对于为每个函数编写而不是指定其他参数来说肯定要容易得多.
setlocal /? 关于ENABLEDELAYEDEXPANSION说这个:
这些修改将持续到匹配的ENDLOCAL命令,无论它们在SETLOCAL命令之前的设置如何.
所以也许这意味着即使与另一个setlocal设置保持不变?
如何检查批处理文件中的变量是否包含特殊字符?例如,如果我的变量包含文件名,则文件名不应包含\/ < > | : * " ?此类字符。
@echo off
set param="XXX"
echo %param%| findstr /r "^[^\\/?%*:|"<>\.]*$">nul
if %errorlevel% equ 0 goto :next
echo "Invalid Attribute"
:next
echo correct
Run Code Online (Sandbox Code Playgroud)
我使用此链接作为参考正则表达式来验证文件夹名称和文件名
这部分工作正常,直到文件名中有一个&符号,在这种情况下它会完全崩溃我的脚本.
echo %filename% | findstr /i /b /c:"%name% (%year%)"
Run Code Online (Sandbox Code Playgroud)
我不能只是将文件名放入引号,因为我需要在开头找到字符串.那我怎么能两个都做?
说我有两个命令:foo和bar.
我想执行这两个操作,使得foo的输出被"重定向"到bar的输入.不仅如此,我还希望写入foo输出流的每个字节直接/立即写入bar的输入流.
如果我使用命令:
foo | bar
Run Code Online (Sandbox Code Playgroud)
然后foo必须在bar开始读取其输入流之前终止/退出.我希望bar在foo写入其输出流的同时开始读取其输入流.
这这里回答,如果我理解正确的话,指出存在由管道缓冲的字节数的限制,当他们充满对准管是"刷新"来也许这个限制可以减少到"栏的输入流不知何故?
将我的脚本分成两个批处理文件,因为我不知道如何组合它:
很短,这样你就明白了:
1.bat:使用参数调用 2.bat,对其输出进行排序并使行唯一
FOR /F ... (2.bat %1 ^| sort) DO (...)
Run Code Online (Sandbox Code Playgroud)
do 部分将行相互比较并使用行缓冲区排除相同的行
2.bat:打印 FOR 循环的结果字符串
FOR ... DO ECHO
Run Code Online (Sandbox Code Playgroud)
在 bash 中,这可能看起来像这样:(管道很容易)
(command) | while read line ; do echo $line ; done | sort | uniq
Run Code Online (Sandbox Code Playgroud)
我真的不知道如何在 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 …Run Code Online (Sandbox Code Playgroud) 我将批处理脚本的命令行参数作为文件名和文件夹的列表.对于每个文件名,我需要打印找到该文件的文件夹的所有子文件夹(该文件的路径).子文件夹名称应按文件大小的降序排序(文件可以在不同的子文件夹中具有各种大小).
到目前为止我已经这样做了,但它不起作用:
::verify if the first parameter is the directory
@echo off
REM check the numbers of parameters
if "%2"=="" goto err1
REM check: is first parameter a directory?
if NOT EXIST %1\NUL goto err2
set d=%1
shift
REM iterate the rest of the parameters
for %%i in %dir do (
find %dir /name %i > temp
if EXIST du /b temp | cut /f 1 goto err3
myvar=TYPE temp
echo "file " %i "is in: "
for %%j in …Run Code Online (Sandbox Code Playgroud) 在Bash中,变量 - 表示命令的stdin,对管道命令非常有用.我想知道Windows批处理文件中是否存在等效文件,我似乎无法找到答案.
这是我在绝对必要时传统上所做的事情(而且if它是最有用的陈述):
<command> | set /p tmpvar=
if "%tmpvar%"=="whatever" rem stuff
Run Code Online (Sandbox Code Playgroud)
我觉得做一些像Bash你可以做的事情会更快更容易.这是Bash中的一个等效脚本,我想要一些比Windows批处理更简单的东西(不需要DOS兼容性).
<command> | if ("-" == "whatever" ) # stuff
Run Code Online (Sandbox Code Playgroud)
是否有比上面第一个例子更简单的东西?这会让事情变得容易多了.