批处理:递归遍历目录和排序文件名

时间:2014-01-28 17:51:17

标签: arrays sorting batch-file recursion

我想循环遍历一个目录并让它的文件名回显。 我遇到了1对01名称的麻烦。 说,我有这个:

D:\Downloads\prefixorder\order\1.txt
D:\Downloads\prefixorder\order\10.txt
D:\Downloads\prefixorder\order\2.txt
D:\Downloads\prefixorder\order\3.txt
D:\Downloads\prefixorder\order\1\new.txt
D:\Downloads\prefixorder\order\10\new.txt
D:\Downloads\prefixorder\order\2\new.txt
D:\Downloads\prefixorder\order\order\1.txt
D:\Downloads\prefixorder\order\order\10.txt
D:\Downloads\prefixorder\order\order\2.txt
D:\Downloads\prefixorder\order\order\20.txt
D:\Downloads\prefixorder\order\order\3.txt
D:\Downloads\prefixorder\order\order2\1.txt
D:\Downloads\prefixorder\order\order2\10.txt
D:\Downloads\prefixorder\order\order2\2.txt
D:\Downloads\prefixorder\order\order2\20.txt
D:\Downloads\prefixorder\order2copy\1.txt
D:\Downloads\prefixorder\order2copy\10.txt
D:\Downloads\prefixorder\order2copy\2.txt
D:\Downloads\prefixorder\order2copy\20.txt
D:\Downloads\prefixorder\order3\1.txt
D:\Downloads\prefixorder\order3\10.txt
D:\Downloads\prefixorder\order3\2.txt
D:\Downloads\prefixorder\order3\20.txt
D:\Downloads\prefixorder\1.txt
D:\Downloads\prefixorder\10.txt
D:\Downloads\prefixorder\2.txt

我想在每个文件夹中列出10个以下1(并且文件夹也按照这样排序)。

基本上看起来像这样:

D:\Downloads\prefixorder\1.txt
D:\Downloads\prefixorder\2.txt
D:\Downloads\prefixorder\10.txt
D:\Downloads\prefixorder\order\1.txt
D:\Downloads\prefixorder\order\2.txt
D:\Downloads\prefixorder\order\3.txt
D:\Downloads\prefixorder\order\10.txt
D:\Downloads\prefixorder\order\1\new.txt
D:\Downloads\prefixorder\order\2\new.txt
D:\Downloads\prefixorder\order\10\new.txt
D:\Downloads\prefixorder\order\order\1.txt
D:\Downloads\prefixorder\order\order\2.txt
D:\Downloads\prefixorder\order\order\3.txt
D:\Downloads\prefixorder\order\order\10.txt
D:\Downloads\prefixorder\order\order\20.txt
D:\Downloads\prefixorder\order\order2\1.txt
D:\Downloads\prefixorder\order\order2\2.txt
D:\Downloads\prefixorder\order\order2\10.txt
D:\Downloads\prefixorder\order\order2\20.txt
D:\Downloads\prefixorder\order2copy\1.txt
D:\Downloads\prefixorder\order2copy\2.txt
D:\Downloads\prefixorder\order2copy\10.txt
D:\Downloads\prefixorder\order2copy\20.txt
D:\Downloads\prefixorder\order3\1.txt
D:\Downloads\prefixorder\order3\2.txt
D:\Downloads\prefixorder\order3\10.txt
D:\Downloads\prefixorder\order3\20.txt

与升级字母表后排序的默认任何win7资源管理器显示的顺序完全相同。 (虽然在那个版本中,根文件的文件会显示在文件夹下面,但这并不重要)。 一个很好的奖励是,无论我拖动它从哪个物体掉落,这个输出都会出现。

我找到了这个,它很好地解决了一个文件夹的这个问题: Read files in directory in order of filename prefix with batch?

我想要递归地解决这个问题的差异,同时可以删除多个文件/文件夹。

我当前的(错误)修改如下所示:

@echo off
setlocal EnableDelayedExpansion
rem Create an array with filenames in right order

if [%1]==[] goto :eof
:loop
for /f "tokens=* delims=" %%a in ('dir "%~1"  /a-d  /s /b') do (
   for /F "delims=-" %%i in ("%%a") do (
      set "number=00000%%~ni"
      set "file[!number:~-6!]=%%a"
   )
)
rem Process the filenames in right order
for /F "tokens=2 delims==" %%f in ('set file[') do (
   echo %%f
)

shift
if not [%1]==[] goto loop


@pause

有问题的最多行似乎是

set "file[!number:~-6!]=%%a"

其数组参数实际上我甚至没有真正开始理解。无论如何,我的猜测是每个循环都会覆盖数组的条目,因为每个循环中的参数几乎相同。

我还怀疑%%〜ni可能是覆盖的原因,因为文件夹内的文件名都是一样的。使用%%〜ni在我看来显然是错误的,但使用%%我根本不再进行任何排序,并在1之前回复10,这更加错误。 但是,如果拖动多个文件夹,它会起作用,因为它们处于单独的回声循环中。我尝试在第一个内循环之前和之后的第一个外循环中放入echo循环。虽然确实没有遗漏任何东西,但根本没有正确排序。

回到主要问题:如何递归地解决这个问题并拖动多个文件/文件夹,对文件名和文件名进行排序。 在递归地在一个文件夹中,foldernames奇怪地没有问题。当拖动多个文件夹/文件时,它会成为一个问题,因为它随后以拖动的对象作为第一个参数开始。

我是否需要使用数组或类似的数组? (尝试调查它,并没有真正得到批量的可能性,但是,通过。)或者还有其他方法可以做到这一点吗?

1 个答案:

答案 0 :(得分:0)

甚至不确定这是否是您所需要的,但只要它可以帮助......

@echo off

    :: Without arguments, just list current folder

    if "%~1"=="" (
        call :recursiveSortedFileFolderList "%cd%"
        goto :eof
    )

    :: Else, create a list of elements to sort
    set "tempFile=%temp%\%~nx0.tmp"
    call :generateList %* > "%tempFile%"
    call :recursiveSortedFileFolderList "%tempFile%"
    del "%tempFile%" >nul
    goto :eof

:generateList
    echo(%~1
    if not "%~2"=="" shift & goto :generateList
    exit /b

:recursiveSortedFileFolderList startFolder 

    setlocal enableextensions disabledelayedexpansion

    :: Prepare padding base
    set "pad=#################################"
    set "pad=%pad%%pad%"
    set "pad=%pad%%pad%"
    set "pad=%pad%%pad%"

    :: paddings for numeric or alphabetic prefixed files and folders
    set "_NPad=%pad%"
    set "_APad=%pad:#=$%"

    :: start work
    call :_doRecursiveSortedFileFolderList "%~1"

    :: cleanup and exit
    endlocal
    exit /b

:_doRecursiveSortedFileFolderList folder
    :: adjust environment for current folder 
    setlocal
    set "timestamp=%time::=%"
    set "tempFile=%temp%\%~nx0.%random%%random%%random%%random%.%timestamp:,=%.tmp"
    set "folder=%~1" & if not defined folder ( set "folder=." ) else ( set "folder=%~f1" )

    :: determine if we are handling a folder or a file with elements in it
    if exist "%folder%\" (
        set "cmd=dir /b ""%folder%\*"" 2^>nul"
    ) else if exist "%folder%" (
        set "cmd=more ""%folder%"" "
        set "folder="
        for /f "tokens=* usebackq" %%a in ("%folder%") do if not defined folder (
            for /f "tokens=*" %%b in ("%%~dpa\.") do set "folder=%%~dpnxb"
        )
    ) else (
        endlocal
        exit /b
    )

    :: For each element in the indicated folder/file, prefix it with the adequated prefix 
    :: depending if it is a file or a folder, and send the output to a temporary file 
    :: that will be sorted (using the adecuate prefix), and processed
    (for /f "tokens=*" %%a in ('%cmd%') do (

        :: determine if file or folder
        if exist "%folder%\%%~nxa\" ( set "type=f" ) else  ( set "type=a" )

        :: determine correct padding
        if "%%~na" geq "a" ( set "name=%_APad%:%%~na" ) else ( set "name=%_NPad%:%%~na" )

        :: generate final padded record
        setlocal enabledelayedexpansion
        echo(!type!:!name:~-260!%%~xa
        endlocal
    ))> "%tempfile%"

    :: Sort the temporary file and for each element on it, if it is a file, echo to console, 
    :: else it is a folder and a recursive call is made to process it
    for /f "tokens=1,2,* delims=:" %%a in ('sort /L "C" "%tempfile%"') do (
        if "%%a"=="a" (echo(%folder%\%%c) else (call %0 "%folder%\%%c")
    )

    :: clean and exit
    endlocal & del "%tempfile%" > nul 2>nul
    exit /b