2016-12-29 159 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

相关问题