2016-12-29 215 views
4

我在文件和文件夾名稱上使用感嘆號()掙扎。 我創建的批處理讀取.txt文件的內容,並將列出的文件從文件夾排序到子文件夾中。
例如:
source.txt內部有:file_1.zipfile_2.zip
稱爲system文件夾具有file_1.zipfile_2.zipfile_3.zip等 和批量讀取source.txt和這兩個文件複製到system/source批處理 - EnableDelayedExpansion,感嘆號和文件/文件夾名稱

我試圖避免啓用啓用DelayedExpansion,但添加文件夾瀏覽器後,我找不出比使用它更好的方法。我需要它啓用了辦法,我展示:listSources:listFolders 我的問題,現在沒有那麼多的處理文件夾名稱(雖然這將是美妙的,允許的話),但允許(!)其名稱上具有(!)的文件的副本。

我想過逃跑^^!該字符或在setlocal和endlocal之間切換,但我仍然在學習如何正確使用它,因此不知道如何處理它。也許有更好的方法? (我不是程序員!)

@echo off 
setlocal EnableDelayedExpansion 

rem Copy sorted files into destination folder? [Y/N] 
set "copyMode=y" 
if /i "%copyMode%"=="y" (set appendTitle=[Copy Mode]) else set appendTitle=[Log Mode] 

rem Set prefix for output file (used only if copyMode=n) 
set prefixMiss=missing_in_ 

rem Set defaults to launch directory 
set rootSource=%~dp0 
set rootFolder=%~dp0 

:listSources 
title Source file selection %appendTitle% 
Show folder names in current directory 
echo Available sources for sorting: 
for %%a in (*.txt) do (
    set /a count+=1 
    set mapArray[!count!]=%%a 
    echo !count!: %%a 
) 

:checkSources 
set type=source 
if not exist !mapArray[1]! cls & echo No source file (.txt) found on current directory^^! & goto SUB_folderBrowser 
if !count! gtr 1 set /a browser=!count!+1 & echo.!browser!: Open Folder Browser? & goto whichSource 
if !count! equ 1 echo. & set /p "oneSource=Use !mapArray[1]! as source? [Y/N]: " 
if /i "%oneSource%"=="y" (set "sourceFile=1" & echo. & goto listFolders) else goto SUB_folderBrowser 

:whichSource 
echo. 
rem Select source file (.txt) 
echo Which one is the source file you want to use? Choose !browser! to change directory. 
set /p "sourceFile=#: " 
if %sourceFile% equ !browser! goto SUB_folderBrowser 
if exist !mapArray[%sourceFile%]! echo. & goto listFolders 
echo Incorrect input^^! & goto whichSource 

:listFolders 
title System folder selection %appendTitle% 
rem Show folder names in current directory 
cd %~dp0 
set count=0 
echo Available folders for sorting: 
for /d %%a in (*) do (
    set /a count+=1 
    set mapArray2[!count!]=%%a 
    echo !count!: %%a 
) 

:checkFolders 
set type=root 
if not exist !mapArray2[1]! cls & echo No folders found on current directory^^! & goto SUB_folderBrowser 
if !count! gtr 1 set /a browser=!count!+1 & echo.!browser!: Open Folder Browser? & goto whichSystem 
if !count! equ 1 echo. & set /p "oneFolder=Use !mapArray2[1]! as target? [Y/N]: " 
if /i "%oneFolder%"=="y" (set "whichSystem=1" & goto whichFolder) else goto SUB_folderBrowser 

:whichSystem 
echo. 
rem Select system folder 
echo Which system do you want to sort? Choose !browser! to change directory. 
set /p "whichSystem=#: " 
if %whichSystem% equ !browser! goto SUB_folderBrowser 
if exist !mapArray2[%whichSystem%]! echo. & goto createFolder 
echo Incorrect input^^! & goto whichSystem 

:createFolder 
rem Create destination folder 
if /i not "%copyMode%"=="y" goto sortFiles 
set destFolder=!mapArray[%sourceFile%]:~0,-4! 
if not exist ".\!mapArray2[%whichSystem%]!\%destFolder%" md ".\!mapArray2[%whichSystem%]!\%destFolder%" 

:sortFiles 
rem Look inside the source file and copy the files to the destination folder 
title Sorting files in progress... %appendTitle% 
for /f "delims=" %%a in ('type "%rootSource%\!mapArray[%sourceFile%]!"') do (
if exist ".\!mapArray2[%whichSystem%]!\%%a" (
    if /i "%copyMode%"=="y" copy ".\!mapArray2[%whichSystem%]!\%%a" ".\!mapArray2[%whichSystem%]!\%destFolder%\%%~nxa" >nul 
    echo %%a 
) else (
    echo. 
    echo %%a missing & echo. 
    if /i not "%copyMode%"=="y" echo %%a >> "%~dp0%prefixMiss%!mapArray2[%whichSystem%]!.txt" 
    ) 
) 

title Sorting files finished^^! %appendTitle% 

popd & pause >nul & exit 

:SUB_folderBrowser 
if !count! lss 1 set /p "openBrowser=Open Folder Browser? [Y/N]: " 
if !count! lss 1 (
    if not "%openBrowser%"=="y" exit 
) 
set count=0 & echo Opening Folder Browser... & echo. 
if "%type%"=="root" echo Select the root system folder, not the system itself^^! 

rem PowerShell-Subroutine to open a Folder Browser 
set "psCommand="(new-object -COM 'Shell.Application')^ 
.BrowseForFolder(0,'Please choose a %type% folder.',0,0).self.path"" 
for /f "usebackq delims=" %%i in (`powershell %psCommand%`) do set "newRoot=%%i" 

if "%type%"=="source" set rootSource=%newRoot% 
if "%type%"=="root" set rootFolder=%newRoot% 

rem Change working directory 
if "%type%"=="source" cls & pushd %rootSource% & goto listSources 
if "%type%"=="root" cls & pushd %rootFolder% & echo Selected source file: !mapArray[%sourceFile%]! & echo. & goto listFolders 

任何幫助將不勝感激!

+1

您只需要'For'循環中的EnableDelayedExpansion。在'For'循環中,你可以使用'%% A'來訪問它,所以你根本不需要它。你可以調用一個函數'call:label %% A',並在那個函數中變成'%1'。用'Goto:EOF'結束一個函數。還要結束主程序。 – 2016-12-29 19:51:03

+0

非常感謝您的及時答覆。因爲我實際上是一個通過研究完成寫作的完整小白,所以我需要時間對您的答案(以及任何其他人)做適當的事情,嘗試實施它,看看我是否能夠以某種方式實現它。現在,我不知道你在暗示什麼,因爲我的問題發生在循環中。但是爲了指引我走向正確的方向,非常感謝! – paradadf

+0

@Noodles他的代碼不包含任何呼叫,因此插入'Goto:Eof'將無濟於事。 @paraduff只使用goto來控制程序流程,很快就會導致[Spaghetti代碼](https://en.wikipedia.org/wiki/Spaghetti_code)沒有人會/可以遵循。 – LotPings

回答

2

當FOR變量包含!時,延遲擴展僅在FOR循環內導致問題。

如果您從循環中調出一個子例程,通常可以避免在FOR循環中延遲擴展。該子程序將被重新進行每次迭代,因此您可以使用正常的%var%變量擴展。但是,CALL顯着降低了速度,所以我想避免它。

有一個簡單的解決方案可以避免延遲擴展,並避免使用帶FINDSTR/N的DIR/B將行號注入目錄輸出中的FOR/F可以輕鬆解析的調用。

例如,這裏是爲ListSources循環的解決方案:

for /f "delims=: tokens=1*" %%A in ('dir /b /a-d *.txt^|findstr /n "^"') do (
    set "mapArray[%%A]=%%B" 
    set "count=%%A" 
    echo %%A: %%B 
) 

您可以輕鬆地將相同的技術,你的第二個循環。

您仍然需要在其他非循環代碼段中延遲擴展以擴展數組值。因此,請先禁用延遲擴展,然後將其啓用:whichSource,在第二個循環之前再次禁用它,然後在最後一個循環之後再次啓用它。請注意,您不能使用ENDLOCAL,否則您將丟失先前定義的數組值。因此,您將在禁用和啓用延遲擴展之間切換時創建一小堆SETLOCAL。

+0

Hi @dbenham!我只是試了一下,工作很好,謝謝!甚至文件和文件夾名稱上的奇怪字符,例如^ =(除!以外)都可以工作!這是我迄今爲止:[sorter.bat v2](http://pastebin.com/Axeshbkf)。應用到文件夾的技術結果是:'('dir/b/a:d^| findstr/n「。」'')'。現在我的問題仍然與延遲擴展有關,並且僅在**:sortFiles **上。我需要DelayedExpansion作爲路徑,但'%% a'不會處理!正因爲如此。你能給我一些建議嗎? – paradadf

+0

我在執行sortFiles for-loop和禁用擴展之前定義了一個變量。通過這樣做,一切都比預期的更好! 您可以在這裏找到該批次的最新工作版本(http://pastebin.com/WraUntEA)。 – paradadf

+2

@paradadf - 很好,但你有一個問題。在一個CALL級別中SETLOCAL的最大數目是32,所以如果你有超過32次迭代,你的循環:sortfiles將會失敗。這是通過添加ENDLOCAL作爲循環的最後一個命令來解決的。這是好的,因爲你沒有在必須保留的循環內設置任何變量。 – dbenham

相關問題