2017-02-26 143 views
0

我需要删除所有未在参数中指定的扩展名(.sys文件除外)的文件。问题出在我的变量的分配上。批处理文件按指定的扩展名删除文件

这里是我的命令(复制道歉,不知道如何使用或在这里的讲话):

@echo off 
cls 
cd test 
for %%f in (*.*) do (
    set exist = false 
    for %%a in (%*) do (
     if %%~xf == .%%a set exist = true 
     if %%~xf == .sys set exist = true 
    ) 
    if %exist% == false ( 
     del %%f 
    ) 
) 
pause 

将是如何得到这个代码工作的任何建议,非常感谢由我预期。

回答

3

您的代码的主要问题是变量扩展。在批处理文件中,当一个命令或一个命令块(包含在括号中的几个命令)被获得时,它们被解析并执行。在解析阶段,变量读取操作(%var%)将从代码中被替换为变量内部的值。一旦完成,命令或块就会执行。所有这一切意味着当执行代码时,如果更改变量(代码中的exists),则在同一个命令/块内部无法检索更改后的值,因为没有任何变量读取操作,只有在开始执行阶段之前变量中的值。

这可以使用setlocal enabledelayedexpansion避免。此命令允许您将需要的语法从%var%更改为!var!,指示解析器必须延迟变量扩展直到命令执行,而不是在解析阶段。

所以,你的代码可能是像

@echo off 
    setlocal enabledelayedexpansion 
    cls 
    cd test 
    for %%f in (*.*) do (
     set "exist=false" 
     for %%a in (%*) do (
      if /i "%%~xf" == ".%%a" set "exist=true" 
      if /i "%%~xf" == ".sys" set "exist=true" 
     ) 
     if "!exist!"=="false" ( 
      del "%%f" 
     ) 
    ) 
    pause  

注意

  • set var = value已改为set var=value。空格很重要,你定义了一个变量var[space],其值为[space]value

  • 所有变量赋值都被引用以防止包含在变量值中的不需要的结束空格。如果包含空格,==测试可能会失败。小心这是不需要的,但这是一个好习惯。都被包括

  • 引号,以防止与在文件名中的空格或扩展

  • %exists%已改变为!exists!如此改变的值可以被检索问题的同时,相同的块内(for %%f

  • if扩展比较包括用于不区分大小写测试的/i开关。

你也应该注意到,当已延迟扩展启用,!性格变得解析器会认为这是一个可变的读取操作的一部分问题。如果您的文件或扩展名可能包含此字符,则延迟扩展是个问题。它可以完成但需要只在真正需要时启用延迟扩展,并在不需要时再次禁用。

@echo off 
    setlocal disabledelayedexpansion 
    cls 
    cd test 
    for %%f in (*.*) do (
     set "exist=false" 
     for %%a in (%*) do (
      if /i "%%~xf" == ".%%a" set "exist=true" 
      if /i "%%~xf" == ".sys" set "exist=true" 
     ) 
     setlocal enabledelayedexpansion 
     if "!exist!"=="false" ( 
      endlocal 
      del "%%f" 
     ) else (
      endlocal 
     ) 
    ) 
    pause 

但是,正如你的情况,你只更改两个值,值是不相关的变量的值,它仅仅是一个标志,你可以忽略延迟扩展和变量中的真正价值和使用替代语法if defined来测试变量是否包含值。你true/false可以是defined/not defined测试

@echo off 
    setlocal enableextensions disabledelayedexpansion 

    cd test 
    for %%f in (*) do (
     set "removeFile=1" 
     for %%x in (sys %*) do (
      if /i "%%~xf"==".%%~x" set "removeFile=" 
     ) 
     if defined removeFile del "%%f" 
    ) 
    pause 

如果扩展匹配任何的参数,变量的内容被删除,也就是现在的变量是不确定的。

编辑适应脱线的评论

当与filesytem元素处理,就可以看到这个文件/文件夹选择意外行为。

不遵循8.3传统命名的文件和文件夹(名称最多8个字符,最多3个扩展名,无特殊字符,无空格)具有所谓的长名称,但它们还有一个简短的8.3名称与长名称关联。可以在dir命令中使用/x开关。

虽然不是直接可见,但是当完成通配符搜索时会检查这些短名称,从而导致选择的文件/文件夹的长文件名或扩展名与所请求的通配符表达式不匹配,但名称或扩展名与通配符匹配。

在需要的情况下内for循环要处理的短名称或扩展,在for替换参数使用的改性剂(例如,%%f)来检索他们是

%%~snxf Short name and short extension of the element being referenced by %%f 
%%~snf  Short name of the element being referenced by %%f 
%%~sxf  Short extension of the element being referenced by %%f 
+1

确实很好。或许你应该加上关于lfn vs sfn的警告。 – Magoo

+0

@Magoo,因为代码对于短文件名/扩展名没有任何问题。搜索不是使用文件的扩展名来完成的,'%%〜xf'如果存在,它将检索长扩展名。 –

+0

@MCND哇!非常感谢,这是非常翔实的! – Igor