FOR循环空格和处理

时间:2016-06-20 16:21:35

标签: batch-file for-loop cmd

我有一个列出所有服务的批处理脚本,接受BINARY_PATH,删除包含c“\ windows”的所有行,并提供BINARY_PATHS列表。

我们的想法是将该列表传递给ICACLS,以确定在每个可执行文件上设置的权限。

我遇到的问题是某些BINARY_PATHS包含前导和尾随“。 因此,我必须通过将delims =“添加到my for / f语句来解释这一点。

以下是输出到ECHO的批处理文件

for /f "tokens=2" %%n in ('sc query state^= all ^| findstr SERVICE_NAME') do (
  for /f "delims=: tokens=1*" %%r in (
    'sc qc "%%~n" ^| findstr BINARY_PATH_NAME'
  ) do (
    for /f tokens^=1-2^ delims^=^" %%x in ('echo %%~s^| findstr /V /I "c:\windows\system32"') do (
         echo "%%~x%%~y" 
        )
  )
)

ECHO输出如下 - 一个漂亮的清洁列表,它与领先的空间区别开来

" C:\Windows\Microsoft.NET\Framework\v2.0.50727\aspnet_state.exe"
" C:\Windows\Microsoft.NET\Framework\v2.0.50727\mscorsvw.exe"
" C:\Windows\Microsoft.Net\Framework\v3.0\WPF\PresentationFontCache.exe"
" C:\Windows\Microsoft.NET\Framework\v3.0\Windows Communication Foundation\infoc
ard.exe"
" C:\Windows\Microsoft.NET\Framework\v3.0\Windows Communication Foundation\SMSvc
Host.exe"
" C:\Program Files\Photodex\ProShow Producer\ScsiAccess.exe"
" C:\Windows\servicing\TrustedInstaller.exe"
" C:\Program Files\VMware\VMware Tools\vmtoolsd.exe"

当我尝试将输出传递给没有前导和尾随的icacls时,它会崩溃,因为某些路径中有空格。

ICACLS批处理文件:

for /f "tokens=2" %%n in ('sc query state^= all ^| findstr SERVICE_NAME') do (
  for /f "delims=: tokens=1*" %%r in (
    'sc qc "%%~n" ^| findstr BINARY_PATH_NAME'
  ) do (
    for /f tokens^=1-2^ delims^=^" %%x in ('echo %%~s ^| findstr /V /I "c:\windows\system32"') do (
         icacls %%~x%%~y 
        )
  )
)

ICACLS批次的一些输出:

C:\Windows\Microsoft.Net\Framework\v3.0\WPF\PresentationFontCache.exe NT SERVICE
\TrustedInstaller:(F)
                                                                      BUILTIN\Ad
ministrators:(RX)
                                                                      NT AUTHORI
TY\SYSTEM:(RX)
                                                                      BUILTIN\Us
ers:(RX)

Successfully processed 1 files; Failed processing 0 files
Invalid parameter "Communication"
Invalid parameter "Communication"
Invalid parameter "Files\Photodex\ProShow"
C:\Windows\servicing\TrustedInstaller.exe NT SERVICE\TrustedInstaller:(F)
                                          BUILTIN\Administrators:(RX)
                                          NT AUTHORITY\SYSTEM:(RX)
                                          BUILTIN\Users:(RX)

Successfully processed 1 files; Failed processing 0 files
Invalid parameter "Files\VMware\VMware"

有什么想法吗?

1 个答案:

答案 0 :(得分:1)

将引号放在引号之间是绝对正确的,以避免出现白色空格问题。 但是,我不会删除和引导和尾随""中包含的空格,而是试图不生成它们而不是在以后消除它们。

前导空格来自中间for /f循环:

for /f "delims=: tokens=1*" %%r in ('sc qc "%%~n" ^| findstr BINARY_PATH_NAME') do ( ... )

过滤的sc qc命令生成输出行,如:

        BINARY_PATH_NAME   : C:\Windows\System32\spoolsv.exe
        BINARY_PATH_NAME   : "C:\Program Files\iPod\bin\iPodService.exe"

使用"delims=: tokens=1*"选项,分隔符(:)后面的部分保留一个前导空格。 要解决此问题,请将空格添加为另一个分隔符,但请确保它是选项字符串中的最后一个字符:"tokens=1* delims=: "

尾随空格来自内部echo循环解析的管道for /f命令行:

for /f tokens^=1-2^ delims^=^" %%x in ('echo %%~s ^| findstr /V /I "c:\windows\system32"') do ( ... )

echo %%~s^|之间的空格也包含在输出中。因此,只需删除它。 没有必要定义选项字符串tokens^=1-2^ delims^=^",因为for /f循环不应该接收任何引号来解析(由于~中的%%~s修饰符),所以"delims="就足够了。因此,仅在循环体中使用%%~x 此外,我建议写echo(%%~s而不是echo %%~s,以便在ECHO is on/off.为空时避免%%~s条消息(尽管这绝不会发生)。

另一个问题是sc query state= all检索的服务名称也可能包含空格;例如:

SERVICE_NAME: iPod Service

因此,对于外部for /f循环,"tokens=2"选项不是最佳选项;在上面的示例中,仅返回iPod。因此,将其更正为"tokens=1*"并忽略forst令牌。

由于只搜索文字字符串,我将findstr实例替换为find除了最后一个,因为find仅支持单个搜索字符串。 我在剩余的findstr实例中添加了另一个搜索字符串,以便覆盖目录C:\Windows\SysWOW64也存在的64位Windows系统,我假设您也要过滤掉。

这是固定代码:

@echo off
for /f "tokens=1*" %%m in ('sc query state^= all ^| find "SERVICE_NAME"') do (
    for /f "tokens=1* delims=: " %%r in ('sc qc "%%~n" ^| find "BINARY_PATH_NAME"') do (
        for /f "delims=" %%x in ('echo(%%~s^| findstr /L /V /I /C:"%SystemRoot%\System32" /C:"%SystemRoot%\SysWOW64"') do (
            ECHO icacls "%%~x"
        )
    )
)

成功测试后删除大写ECHO以执行icacls命令行。