创建一个小批处理文件来管理文件

Creating a little Batch file to manage files

首先,对不起,如果我的英语不好,我来自西班牙。

我有一堆文件(数千个),分布在名为 INSTANCE 的文件夹内的一堆文件夹(几十个)中。只有 2 种文件类型(*.new、*.old)。并非每个文件夹中都有他们两个。我需要将每 100 个 *.new 文件移动到一个新文件夹中。如果存在任何 *.old 文件,请将它们全部移动到单独的文件夹中。我试过手动完成,但几个小时后我意识到这是一项主要任务,所以我想知道是否可以使用批处理文件来完成,一次所有文件夹或在每个文件夹中完成在 INSTANCE 文件夹中。

这听起来可能令人困惑,我首先展示一个现在的例子,然后展示它必须如何的第二个例子(而不是 100s,我展示 3s 的组)。

之前:

D:\[2016]\[01 JANUARY]\INSTANCE
│
├───aaa
│       01.new
│       02.new
│       03.new
│       04.new
│       05.new
│       13.old
│       14.old
│
├───bbb
│       01.new
│       02.new
│       03.new
│       04.new
│       05.new
│       06.new
│       07.new
│       08.new
│       13.old
│       14.old
│       15.old
│
├───ccc
│       01.new
│       02.new
│       03.new
│       04.new
│       05.new
│
└───ddd
        01.new
        02.new
        03.new
        04.new
        05.new
        06.new
        07.new
        08.new
        09.new
        11.old

之后:

D:\[2016]\[01 JANUARY]\INSTANCE
│
├───aaa
│   ├───01
│   │       01.new
│   │       02.new
│   │       03.new
│   │
│   ├───02
│   │       04.new
│   │       05.new
│   │
│   └───zz
│           13.old
│           14.old
│
├───bbb
│   ├───01
│   │       01.new
│   │       02.new
│   │       03.new
│   │
│   ├───02
│   │       04.new
│   │       05.new
│   │       06.new
│   │
│   ├───03
│   │       07.new
│   │       08.new
│   │
│   └───zz
│           13.old
│           14.old
│           15.old
│
├───ccc
│   ├───01
│   │       01.new
│   │       02.new
│   │       03.new
│   │
│   └───02
│           04.new
│           05.new
│
└───ddd
    ├───01
    │       01.new
    │       02.new
    │       03.new
    │
    ├───02
    │       04.new
    │       05.new
    │       06.new
    │
    ├───03
    │       07.new
    │       08.new
    │       09.new
    │
    └───zz
            11.old

总结:

Look inside INSTANCE

  for every folder inside

    if any *.old file exists create a folder called ZZ and move there all of them

  Then

    create folder 01 and move 100 of the *.new files
    create folder 02 and move the next 100
    create folder 03 and move the next 100
    ...

Until all the files have been moved

在搜索如何做之前,因为我不是程序员,所以我想知道这是否可能并且对我来说值得学习曲线,因为这是一次性的事情。我读到有一些命令可以帮助完成某些任务(MD、IF EXIST、MOVE 等...),但如果我可以在一个批处理文件中完成所有这些任务就不行了。

提前致谢。

@ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir\t w o\instance"
SET /a filesperdir=3
PUSHD "%sourcedir%"

REM For each directory found in "sourcedir"
FOR /f "delims=" %%a IN (
 'dir /b /ad "*" '
 ) DO (
 SET "dirname=%%a"
 REM initialise subdirectory counter and file counter
 SET /a subcount=0
 SET /a filecount=filesperdir
 REM scan for files "*.new"
 FOR /f "delims=" %%c IN (
  'dir /b /a-d ".\%%a\*.new" 2^>nul'
  ) DO (
   REM name of file and move
   SET "filename=%%c"
   CALL :movenew
 )
 REM scan for files "*.old"
 FOR /f "delims=" %%c IN (
  'dir /b /a-d ".\%%a\*.old" 2^>nul'
  ) DO (
   rem move to "zz"
   MD ".\%%a\zz" >NUL 2>NUL
   ECHO(MOVE ".\%%a\%%c" ".\%%a\zz\"
 )
)

popd

GOTO :EOF

:movenew
REM one more file...
SET /a filecount +=1
REM filled this subdirectory?
if %filecount% gtr %filesperdir% SET /a subcount+=1&SET /a filecount=1
SET /a subnum=1000+subcount
REM try to make subdirectory
MD ".\%dirname%\%subnum:~-2%" >nul 2>nul
ECHO(MOVE ".\%dirname%\%filename%" ".\%dirname%\%subnum:~-2%\"
GOTO :eof

您需要更改 sourcedir 的设置以适合您的情况。

所需的 MOVE 命令仅 ECHOed 用于测试目的。 确认命令正确后,将ECHO(MOVE 更改为MOVE 以实际移动文件。附加 >nul 以禁止报告消息(例如 1 file moved

我在线评论了这项工作是如何完成的。请注意,您需要使用 rem 而不是 ::(通常用作更快输入的替代方法),因为这个技巧(:: 代替 REM)不起作用在代码块内(带括号的一系列语句)

粗略:对于找到的 reac 子目录,将子目录数设置为 0,将文件数设置为最大值。首先处理 .new 文件的子目录,然后处理 .old。对于old个文件,处理简单;只需将它们移动到子目录 zz。对于 new 个文件,运行 子例程 movenew.

:movenew 将 count-of-files-moved 加 1,如果结果大于允许的数量,则增加子目录计数并重置文件计数。

然后使用 subnum 计算子目录名称(字符串的最后 2 个字符)- 将 1000 添加到 subcount 可确保 subnum 始终为 4 位数字. 然后创建目录并移动文件。

请注意,如果目录已经存在,md 将创建一条错误消息。 2>nul 抑制此错误消息。 dir 命令中的 2^>nul 对于包含目标文件类型 none 的目录具有类似的目的。插入符号 ^ 告诉处理器 > 是正在执行的命令的一部分,而不是 for 本身。

@echo off
setlocal EnableDelayedExpansion

rem Look inside INSTANCE
cd /D "D:\[2016]\[01 JANUARY]\INSTANCE"

rem for every folder...
for /D %%f in (*) do (
   rem ... inside
   cd "%%f"

   rem if any *.old file exists...
   if exist *.old (
      rem ... create a folder called ZZ...
      md ZZ
      rem ... and move there all of them
      move *.old ZZ
   )

   rem Then, create folders with two-digits and move 100 *.new files to each one
   set /A twoDigits=100, files=-1
   for %%a in (*.new) do (
      set /A files+=1, filesMOD100=files%%100
      rem Every 100 files, when the remainder of files/100 is zero...
      if !filesMOD100! equ 0 (
         rem ... create a new two-digits folder
         set /A twoDigits+=1
         md !twoDigits:~-2!
      )
      move "%%a" !twoDigits:~-2!
   )

   rem Go back to original folder -INSTANCE-
   cd ..

)