MS Windows批处理文件:需要多行循环

时间:2019-06-20 22:05:35

标签: batch-file

我希望批处理文件删除不需要的文件夹;其命令的宽度必须有限。

这就是我正在工作的内容,但是太长了:

for /d /r . %%d in (Debug,.vs) do @if exist "%%d" rd /s/q "%%d"

此版本应根据我在其他页面上看到的内容工作,但不是:

for /d /r . %%d in (Debug,.vs) do ^
   @if exist "%%d" rd /s/q "%%d"

其输出为

C:\Project1>for / %d in (Debug .vs) do    @if exist "%d" rd /s/q "%d" 

C:\Project1>   @if exist "C:\Project1\Debug" rd /s/q "C:\Project1\Debug" 
' ' is not recognized as an internal or external command, 
operable program or batch file.

C:\Project1>   @if exist "C:\Project1\.vs" rd /s/q "C:\Project1\.vs" 
' ' is not recognized as an internal or external command, 
operable program or batch file.

C:\Project1>for / %d in (Debug .vs) do    @if exist "%d" rd /s/q "%d" 
' ' is not recognized as an internal or external command, 
operable program or batch file.

C:\Project1>   @if exist "C:\Project1\Debug" rd /s/q "C:\Project1\Debug" 
' ' is not recognized as an internal or external command, 
operable program or batch file.

C:\Project1>   @if exist "C:\\.vs" rd /s/q "C:\Project1\.vs" 
' ' is not recognized as an internal or external command, 
operable program or batch file.

...

我也尝试了不带^的变体:

for /d /r . %%d in (Debug,.vs) do (
   @if exist "%%d" rd /s/q "%%d"
)

这确实删除了东西,但是它也提供了一些奇怪的输出:

C:\Project1>for / %d in (Debug .vs) do    @if exist "%d" rd /s/q "%d" 

C:\Project1> ()

C:\Project1> ()

C:\Project1> ()

C:\Project1> ()

...

只需取消()即可让我“该命令的语法不正确。”

2 个答案:

答案 0 :(得分:2)

您可以在CMD提示符中粘贴比显示的内容更长的行,只是将其向右滚动(或向左滚动,具体取决于您的查看方式)

但是,您正在变量名中使用%%,这意味着您必须在CMD / BAT脚本中运行它。这将允许更长的线长。

所以应该没问题:

REM Single Line:
FOR /R %%D in (Debug,.vs) DO @( ECHO Checking: "%%~D" &  IF EXIST "%%~D" ( ECHO. Found! - Removing: "%%~D" ... & RD /S /Q "%%~D" ) )

或更小,如果您确实需要它:

REM Even Smaller Single Line:
FOR /R %%D in (Debug,.vs) DO @(IF EXIST "%%~D" (RD /S/Q "%%~D"))

更小-忽略不存在的目录错误

REM Even Smaller Single Line:
FOR /R %%D in (Debug,.vs) DO @(RD /S/Q "%%~D") 2>Nul

最小的单行,但输出看起来很混乱

REM Even Smaller Single Line:
FOR /R %%D in (Debug,.vs) DO (RD/S/Q "%%D")

现在,如果出于任何原因要使其尽可能小并且正在使用cmd脚本,则可以在每次打开和关闭Paren之后放置回车符,并且可以将回车符放在条件中的各个条款之间

多行:

FOR /R %%D in (
 Debug
 .vs
) DO @(
 ECHO Checking: "%%~D" 
 IF EXIST "%%~D" (
  ECHO. Found! - Removing: "%%~D" ...
  RD /S /Q "%%~D"
 )
)

无论出于何种原因,几乎没有人按照他们的标准进行上述操作,但这是一个完全有效的选择。

多行文件中最短的行可能是

@ECHO OFF
FOR /R %%D in (
Debug
.vs
) DO (
RD /S /Q "%%~D"
)

并且Are是CMD CLI版本。如果您信任,可以粘贴的内容比您看到的要多:

FOR /R %D in (Debug,.vs) DO @( ECHO Checking: "%~D" &  IF EXIST "%~D" ( ECHO. Found! - Removing: "%~D" ... & RD /S /Q "%~D" ) )

如果不能,则更小:

FOR /R %D in (Debug,.vs) DO @(IF EXIST "%~D" (RD/S/Q "%D")

正如我之前提到的,您可以使用将回车符直接粘贴到CMD提示符中的相同方法,人们通常不会这样做,因为它更可能在粘贴到cmd提示符中时破裂,但是您的要求是代码非常简单,因此将其直接粘贴到CMD Prompt中完全有效:

原始的最小多行CMD提示版本:

@ECHO OFF
FOR /R %D in (
Debug
.vs
) DO @(
RD /S/Q "%~D"
)

此外,您只需要使用FOR /R %D,当您编写FOR /D /R . %D时,CMD会简单地忽略/ D并更改为/ R语法,同样是。不需要,因为如果未选择基本目录,则暗示您正在使用.

放弃不必要的字符将为您节省另外三个字符:)

FOR /R自动遍历目录树,而/D必须通过使用通配符来强制这样做,而在/R之后添加/D本质上会导致循环以忽略/D并改用/R语法,并且仅在使用通配符(不使用通配符)时有所不同。

此外:

正如我最初在评论中向另一位成员提到的那样,有更多便捷的方法可以使用.vs使用debugDIR查找目录,这将更快地列出它们,和FindStr相比查找它们是否存在要快得多。

由于与该成员的不必要的讨论,昨晚我没有时间讨论为什么没有必要在列出的命令中添加/D,但是,我将其中的第一稿放在这里。

这是最小的最大所需长度,无需袖口即可进行变量替换(长度为25个字符),可以在CMD行上运行:

最小的CMD-LINE FindStr v,无需更换(袖口25):

@ECHO OFF
FOR /F "tokens=*" %A IN (
'DIR
  /AD/B/S
^|
 FINDStr /I /R
  /C:"\\\.vs$"
  /C:"\\debug$"
') DO @( RD/S/Q "%A")

实际上,我们还可以做另一件事,将其减小到与上一个命令(Len 14)相同的最大大小,而在技术上并未使用变量替换,我们可以将其包装在另一个FOR / F循环中。

额外的循环只是打印,可以设置为不执行任何操作,这样可以使其更快,但是内部循环或外部循环可以执行删除操作(我选择了内部循环)

最小的CMD-LINE FindStr v使用第二个不带变量替换的循环(Len 14):

@ECHO OFF
FOR /F %a IN (
'FOR /F
"UseBackQ"
%A IN (
`DIR
/AD/B/S
^^^|
FINDStr /I /R
/C:"\\\.vs$"
/C:"\\debug$"
`^) DO @(
ECHO."%A"
RD /Q/S "%A"
^) ') DO @(
ECHO.Gone: %a)

如果要进入变量替换,则最小行长可能约为10个字符。

稍后还会发布

答案 1 :(得分:1)

您最新的代码for /r . %%d in (Debug,.vs) do @if exist "%%d" rd /s/q "%%d"并不是最有效的方法。它将\Debug\.vs附加到当前目录的每个子目录中,然后在发出If Exist命令之前,通过RD命令将每个(每个子目录2个) debug命令针对已存在的命令。没有确定该目录是否存在的特定声明。例如,名为RD的无扩展名文件当前将传递给您的for /r . %%d in (Debug,.vs) do @if exist "%%d\" rd /s/q "%%d"命令。可以通过添加尾部反斜杠For来轻松解决此问题。但是,这会在您的命令中添加另一个字符,可以通过删除/R的{​​{1}}选项(如Ben的answer中解释的)的默认当前目录规范来否定该字符。 em>,例如for /r %%d in (Debug,.vs) do @if exist "%%d\" rd /s/q "%%d"

现在,您已经向我们显示了最大行数在每行6062个字符之间,(初始行字符长度为63,最新值为{{1} }),我认为我会提供一些60示例代码:

Dir

根据Ben的comment 的建议,使用@For /F "Delims=" %%A In ( 'Dir /B/S/AD Debug .vs 2^>NUL' )Do @RD /S/Q "%%A" 2>NUL 也可以提供替代解决方案:

FindStr

上面提到的一件小事,将@For /F "Delims=" %%A In ( 'Dir /B/S/AD 2^>NUL^|FindStr /I "\\Debug$ \\\.vs$"' )Do @RD /S/Q "%%A" 2>NUL Debug的子目录作为.vs或{{1}的子目录存在是可行的}。 将属于已删除子目录的兄弟姐妹传递给另一个删除进程似乎有点愚蠢。为了防止这种情况,尽管没有对速度进行测试,但我认为它不会比我之前的示例慢很多,甚至可以通过第二个Debug命令通过管道传递它:

.vs

上面的示例还增加了安全性,以过滤掉所有潜在的系统目录并重新解析点。

尽管上述所有解决方案显然都比FindStr个字符长,但我试图将所有字符都保持在最大行数限制内,同时试图保持平衡和可读性。 < / p>