将文件组织到文件夹中,然后根据文件名组织子文件夹

Organize files into folders then subfolders based on filenames

一组文件具有“主文件夹名称”(显式)和一个子文件夹名称 (hinted) 在他们的文件名中。

目的是通过“主文件夹名称”和子文件夹名称将它们组织在新文件夹中 然后使用批处理脚本将所有文件移动到相应的新文件夹。

示例:

|>源目录

|>Main Folder Name (0001) S01E01 - FileDescription.bmp
|>Main Folder Name (0001) S01E01 - FileDescription.srt
|>Main Folder Name (0001) S01E02 - FileDescription.bmp
|>Main Folder Name (0001) S01E03 - FileDescription.bmp
|>Main Folder Name (0001) S01E03 - FileDescription.srt
|>Main Folder Name (0007) S03E01 - FileDescription.jpg
|>Main Folder Name (0007) S03E02 - FileDescription.png
|>Main Folder Name (0007) S03E03 - FileDescription.srt
|>Main Folder Name (0012) S25E01 - FileDescription.ico
|>Main Folder Name (0012) S25E02 - FileDescription.txt

预期结果

|>源目录

|>Main Folder Name (0001)
    |>SubFolderName 1
        |>Main Folder Name (0001) S01E01 - FileDescription.bmp
        |>Main Folder Name (0001) S01E01 - FileDescription.srt
        |>Main Folder Name (0001) S01E02 - FileDescription.bmp
        |>Main Folder Name (0001) S01E03 - FileDescription.bmp
        |>Main Folder Name (0001) S01E03 - FileDescription.srt

|>Main Folder Name (0007)
    |>SubFolderName 3
        |>Main Folder Name (0007) S03E01 - FileDescription.jpg
        |>Main Folder Name (0007) S03E02 - FileDescription.png
        |>Main Folder Name (0007) S03E03 - FileDescription.srt

|>Main Folder Name (0012)
    |>SubFolderName 25
        |>Main Folder Name (0012) S25E01 - FileDescription.ico
        |>Main Folder Name (0012) S25E02 - FileDescription.txt

花了几天时间尝试并从其他帖子中吸取技巧,但事实证明我对批处理命令的掌握对于这项任务来说太基础了。

这是我的工作伪代码:

1. Take first file
2. Search for the string pattern S??E?? to give away:

    FolderName = All chars on the left of S??
    SubFolderNumber = NumericValue of ?? in S??

3. MakeDir \FolderName\"SubFolderName " + SubFolderNumber
4. Move the file to that new subfolder in step #3
5. Recurse and do steps 1-4 to each file until the end of the list

步骤 #2 对于这个社区的专家来说可能太简单了,但它并不能阻止我的手拉扯我的头发。 :D

非常感谢任何愿意抽出时间帮助我留住剩下的头发的人。

苦思冥想出了一个ver1.0.

还没有fool-proof,但现在可以了。虽然有点慢。需要一位好心的专家进行一些调整,也许是更好的方法,甚至是大修。

非常欢迎您提出建议。

@ECHO OFF
SETLOCAL EnableDelayedExpansion
FOR %%a in (*) DO (
    SET FileName=%%~na
    CALL:findString FileName ") S" pos
    SET /A pos=pos+1
    SET /A pos2=pos+2
    CALL SET "NewFolderName=%%FileName:~0,!pos!%%"
    CALL SET "NewSubFolderNumber=%%FileName:~!pos2!,2%%"
    SET /A NewSubFolderNumber=NewSubFolderNumber
    SET NewSubFolder="%%~pa!NewFolderName!\SubFolderName !NewSubFolderNumber!\"
    SET str="%%~fa" !NewSubFolder!
    MD !NewSubFolder!
    MOVE !str!
)

寻找就会找到。在网上的某个地方及时发现了这个丢失的 link,以挽救我剩下的一缕头发。 (有人知道为什么一开始就没有 built-in INSTR() 函数吗?)

:findString -- returns position of first occurrence of a string in another string, case sensitive, maximum string length is 1023 characters
::          -- %~1: in - varible name of a string to be searched
::          -- %~1: in - string to be found
::          -- %~3: out- return variable name, will be set to position or undefined if string not found
:credit belongs to
:$source http://www.dostips.com
:Posted By: DosItHelp
:Expert
:Posts: 239
:Joined: 18 Feb 2006 19:54

SETLOCAL ENABLEDELAYEDEXPANSION
set "pos="
set "str=!%~1!"
for /L %%a in (0,1,1023) do (
   set "s=!str:~%%a!"
   if not defined pos if "%~2!s:*%~2=!"=="!s!" set "pos=%%a"
)
ENDLOCAL & IF "%~3" NEQ "" SET "%~3=%pos%"
GOTO:EOF

希望这对其他人有帮助。

@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION 

rem The following setting for the source directoryis a name
rem that I use for testing and deliberately includes spaces to make sure
rem that the process works using such names. These will need to be changed to suit your situation.

SET "sourcedir=u:\your files"
PUSHD "%sourcedir%"

FOR /L %%s IN (0,1,9) DO FOR /L %%t IN (0,1,9) DO IF EXIST "* S%%s%%tE*" (
 FOR /L %%e IN (0,1,9) DO FOR /L %%f IN (0,1,9) DO IF EXIST "* S%%s%%tE%%e%%f -*" (
  FOR /f "delims=" %%b IN ('dir /b /a-d "* S%%s%%tE%%e%%f -*"') DO (
   SET "fullname=%%b"
   FOR /f "tokens=1,2delims=:" %%q IN ("!fullname: S%%s%%tE%%e%%f =:!") DO (
    IF %%s==0 (
rem     MD "%%q\%%t" 2>nul
rem     MOVE "%%b" "%%q\%%t\" >nul
     ECHO MD "%%q\%%t"
     ECHO MOVE "%%b" "%%q\%%t\"
    ) ELSE (
rem     MD "%%q\%%s%%t" 2>nul
rem     MOVE "%%b" "%%q\%%s%%t\" >nul
     ECHO MD "%%q\%%s%%t"
     ECHO MOVE "%%b" "%%q\%%s%%t\"
    )

   )
  )
 )
)

dir/s

popd

GOTO :EOF

此批处理旨在REPORT它打算做什么,并且应该在将其应用于您的实时数据之前针对测试目录进行测试。

当您对结果满意时,从mdmove两行中删除rem注释关键字以激活。如果需要,可以删除 echo 行。

末尾的dir/s简单的显示了结果。

这里的关键是字符串S??E??.

通过%%s%%t依次设置为0..9,我们可以看到是否有一个名为* S00E*.. * S99E* 存在。如果存在这样的文件,请使用 %%e%%f 重复此方法以找到 * S00E00 -*..* S99E99 -*.

然后使用 /b 获取文件名列表 names-only,使用 /a-d 获取没有目录名的文件名列表,匹配特定的 S??E??计算出的字符串,赋值给%%b.

我们需要分析 %%b 所以需要 delayedexpansion 并转移到一个常规变量 fullname 来这样做。

由于文件名不包含:,只需替换:检测到的S??E??并使用for/f tokens delims 选项用于在 S??E?? -> : 处断开名称 %%r 设置为之后的部分,%%q 设置为之前的部分。 %%r在此过程中未使用。

那么就是在%%q中建立子目录,在%%s%%s%%t中建立sub-subdirectory。

如果目录是 re-created,2>nul 会抑制创建的 directory exists 消息,move 命令上的 >nul 会抑制 [=48] =] 消息。