对于/ R循环来创建文件夹没有无限的嵌套

时间:2016-09-12 14:11:18

标签: batch-file for-loop recursion cmd

我有一系列文件夹和子文件夹,如下所示:

C:\Images\Annie\2016-09-09_Annie_PC\
C:\Images\Bill\2016-09-06_Bill_PC\
C:\Images\Charlie\2016-08-29_Charlie_PC\

过时的文件夹(例如2016-09-09_Annie_PC)应包含多个.CR2文件。

我想使用FOR / R循环仅输入日期文件夹并创建三个子文件夹(CR2S,DNGS,JPEGS),然后将.CR2文件从日期文件夹移动到CR2S文件夹中。

文件夹树应如下所示:

C:\Images\Annie\2016-09-09_Annie_PC\CR2S\ (containing .CR2 files)
C:\Images\Annie\2016-09-09_Annie_PC\DNGS\
C:\Images\Annie\2016-09-09_Annie_PC\JPEGS\
C:\Images\Bill\2016-09-06_Bill_PC\CR2S\ (containing .CR2 files)
C:\Images\Bill\2016-09-06_Bill_PC\DNGS\
C:\Images\Bill\2016-09-06_Bill_PC\JPEGS\
C:\Images\Charlie\2016-08-29_Charlie_PC\CR2S\ (containing .CR2 files)
C:\Images\Charlie\2016-08-29_Charlie_PC\DNGS\
C:\Images\Charlie\2016-08-29_Charlie_PC\JPEGS\

我已经尝试了下面的批处理文件,它创建了无限的嵌套CR2S文件夹

for /r %a in (.) do @if exist "%%~fa\*.cr2" echo %%~fa & mkdir "%%~fa\CR2S" & mkdir "%%~fa\DNGS" & mkdir "%%~fa\JPEGS" & move "%%~fa\*.CR2" "%%~fa\CR2S\"

上述代码的输出类似于:

C:\Images\Annie\2016-09-01_Annie_PC\CR2S\CR2S\CR2S\CR2S\CR2S\CR2S\CR2S\CR2S\CR2S\CR2S\CR2S\CR2S\CR2S\CR2S\31234100514197.CR2

如何在不生成嵌套CR2S子文件夹的情况下将.CR2文件移动到CR2S文件夹中?

1 个答案:

答案 0 :(得分:1)

问题在于,当您在文件夹上递归迭代时,如果找到了文件,您就是在动态修改文件夹内容(通过创建新的 CR2S 文件夹并将文件移到里面),所以for循环也在拾取新文件夹,并且它永远重复相同的操作(无限递归)。这通常在 StackOverflow 发生时停止,但现在

  

文件名或扩展名太长。

发生得越早。

此方法使用递归函数(标签)来首先处理子文件夹(因此创建新的子文件夹并在从堆栈返回时复制文件),因此不再遇到相同的无限递归问题。

备注

  • 我没有创建 JPEGS DNGS (或者它应该是 PNGS ?)文件夹,因为我没有'找到它们相关(检查代码中的注释(rem))。
  • 每次运行脚本时,它都会将文件移动到其他 CR2S 子文件夹中。不再有效:请检查 @ EDIT0

以下是代码:

@echo off
setlocal enabledelayedexpansion

set _CR2SDIR=CR2S
set _ROOTDIR="."

call :handle_folder %_ROOTDIR%
goto :eof

:handle_folder
    for /f %%f in ('dir /b /a:d "%~1"') do (
        if "%%f" neq "!_CR2SDIR!" (
            call :handle_folder "%~1\%%f"
        )
    )
    if exist "%~1\*.cr2" (
        if not exist "%~1\!_CR2SDIR!" (
            mkdir "%~1\!_CR2SDIR!"
        )
        rem If needed, do the same for the other 2 subfolders
        move "%~1\*.cr2" "%~1\!_CR2SDIR!"
    )
    goto :eof

:: Old code; it won't be reached

for /r %%a in (.) do (
    if exist "%%~fa\*.txt" (
        echo %%~fa & mkdir "%%~fa\CR2S" & mkdir "%%~fa\DNGS" & mkdir "%%~fa\JPEGS" & move "%%~fa\*.txt" "%%~fa\CR2S\"
    )
)

@ EDIT0 :为了解决 Comment0 (不是初始请求的一部分),我必须在:handle_folder中添加一个额外的检查:如果子文件夹的名称是 CR2S ,然后完全忽略它(我也做了一些参数化)。请注意,在某些情况下,这可能不是预期的行为!