2017-02-26 202 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

相關問題