如何使用BATCH文件命令字符串随机化文件名?

时间:2014-09-07 20:40:07

标签: windows batch-file random command-line rename

我有1个目录包含85 * .bmp图像。每个文件的名称如下所示:

1.bmp
2.bmp
3.bmp
4.bmp
... (and so on...)

我需要自动随机化文件名,但名称必须是1到85范围内的数字。 结果例如1.bmp可以在72.bmp中重命名,如果我再次运行命令字符串,这个72.bmp可以在15.bmp中重命名。但它不能是157.bmp的86.bmp,因为它超出了1到85的范围。 PS 当然,名字一次可以是相同的。

如何使用简单的Windows命令提示符和批处理文件完成?

由于

5 个答案:

答案 0 :(得分:2)

不确定它有多简单:

@echo off

setlocal enableDelayedExpansion

set set_flag=0

pushd "%~1"
for /f %%A in ('dir /a-d-s-h /b *.bmp ^| find /v /c ""') do set files_count=%%A

for /l %%# in (1;1;!files_count!) do (

    set set_flag=0
    set /a rnd=!RANDOM!*85/32768+1

    if not defined rand_!rnd! (
        rem echo setting !rnd! to %%# in outer function 
        set rand_!rnd!=%%#
    ) else (
        call :forward !rnd! %%#
        if !set_flag! EQU 0 call :backward !rnd! %%#
    )
)

rem set rand_

for /f "tokens=2,3 delims==_" %%a in ('set rand_') do (
    rem echo %%a.bmp to %%b.bmp_ 
    REN %%a.bmp %%b.bmp_   2>nul 
)

for /l %%# in (1=1=!files_count!) do (
    rem echo %%#.bmp_ to %%#.bmp
    ren %%#.bmp_ %%#.bmp
)
endlocal
popd
exit /b 0
:backward
    set up_limit=%~1
    set set_to=%~2

    setlocal enableDelayedExpansion
    for /l %%$ in (!up_limit! , -1 , 1 ) do (
        if not defined rand_%%$ (
            set inner_rnd=%%$
            rem echo setting !inner_rnd! to %set_to% from :backward
            set /a rand_!inner_rnd!=%set_to%
            goto :break_back
        )
    )
    endlocal && goto :eof
    :break_back
    endlocal & (
      set rand_%inner_rnd%=%set_to%
    )
:forward
    set down_limit=%~1
    set set_to=%~2

    setlocal enableDelayedExpansion
    for /l %%$ in (!down_limit! , 1 , !files_count! ) do (
        if not defined rand_%%$ (
            set inner_rnd=%%$
            rem echo setting !inner_rnd! to %set_to% from :forward
            set /a rand_!inner_rnd!=%set_to%
            set set_flag=1
            goto :break_forward
        )
    )
    endlocal && goto :eof
    :break_forward
    endlocal & (
      set rand_%inner_rnd%=%set_to%
      set set_flag=%set_flag%
    )

我认为仅仅通过等待%random%生成所有数字来等待所有数字填充是疯狂的。所以我创建了:向后和:转发函数以便更快地生成。

编辑 10:05:57 (GMT + 0:00) - 重命名部分固定。 根据新要求编辑编辑。现在它接受该目录作为第一个参数并计算.bpm个文件。 要对所有子目录执行此操作(假设脚本保存为randomizer.bat),请将其与脚本的实际路径一起使用:

@echo off
for /d /r %%# in (*) do call c:\randomizer.bat "%%~#"

答案 1 :(得分:2)

此代码应随机化所有BMP文件名:

编辑:代码现在计算文件夹中的BMP文件数。 1.bmp 2.bmp 3.bmp ... nn.bmp

@echo off
if not exist *.bmp echo no bmp files found&pause&goto :EOF
setlocal enabledelayedexpansion
set num=0
for %%a in (*.bmp) do set /a num+=1
for /L %%a in (1,1,%num%) do (set A%%a=&set B%%a=)

:loop
for /L %%a in (1,1,%num%) do (
   for /L %%b in (1,1,500) do (
      if not defined A%%a set /a "B=(!random! %% %num%) + 1" & if not defined B!b! set A%%a=ren "%%a.bmp" "!b!.zzz" & set B!b!=1 
   )
)
for /L %%c in (1,1,%num%) do if "!A%%c!"=="" goto :loop  
for /L %%c in (1,1,%num%) do !A%%c!
ren *.zzz *.bmp
pause

答案 2 :(得分:1)

这是一个独立于文件数量的文件(尽管它确实需要将它们命名为1.bmp到n.bmp)。

它还使用+1幻灯片,因此它不依赖于%random%最终命中所有可能的值。这可能会花费您少量的随机性,但是一旦有了解决方案,您就可以多次运行它。

同样不需要enabledelayedexpansion,但我认为我在世界上唯一没有使用它的地方工作。

setlocal
set TEMPPREFIX=__TEMPBITMAP_
set FILEEXTENSION=bmp

for /f %%a in ('dir/b *.%FILEEXTENSION% ^| find /C "."') do set countfiles=%%a

for /L %%a in (1 1 %countfiles%) do call :RandomizeSingleFile %%a

:: Strip temp prefix from all files
for /L %%a in (1 1 %countfiles%) do ren %TEMPPREFIX%%%a.%FILEEXTENSION% %%a.%FILEEXTENSION%

endlocal & goto :eof

:RandomizeSingleFile
setlocal
set oldfilename=%1.%FILEEXTENSION%

set /a num=(%random% %% %countfiles%) + 1

:GetNewNumber_iterate
set newfilename=%TEMPPREFIX%%NUM%.%FILEEXTENSION%

if exist %newfilename% (
  set /a num=%num%+1
  if %num% GEQ %countfiles% set num=1
  goto :GetNewNumber_iterate
)

ren %oldfilename% %newfilename%

endlocal & goto :eof

在包含8个,25个和500个bmp文件的目录上测试。

答案 3 :(得分:1)

下面的批处理文件将当前文件夹中的任意数量的* .bmp文件重命名为最大值999,并且文件名中不需要任何格式。此外,我认为这是实现这一过程的最快方式。

@echo off
setlocal EnableDelayedExpansion

rem Load file names and create a list of numbers in natural order
rem with a separation space and three characters each
set i=0
set "list="
for %%a in (*.bmp) do (
   set /A i+=1
   set "file[!i!]=%%a"
   set "num=   !i!"
   set "list=!list!!num:~-4!"
)
set "list=%list% "

rem Extract random elements from the list of numbers
rem and use they to rename the files
for /L %%i in (%i%,-1,1) do (
   set /A "randElem=!random! %% %%i * 4"
   for %%r in (!randElem!) do for /F "delims=" %%s in ("!list:~%%r,4!") do (
      for /F %%a in ("%%s") do ECHO ren "!file[%%i]!" "%%a.bmp"
      set "list=!list:%%s = !"
   )
)

请注意,ren命令仅显示在屏幕上, NOT 已执行。如果命令正确,请删除ECHO部分以执行它们。

答案 4 :(得分:1)

另一个。编码为子程序在@Aacini的答案中使用了类似的想法。将所有文件读入一个数组,然后将数组洗牌,重命名为shuffle进程文件。

在这种情况下,文件会逐个重命名为临时扩展名,以避免在处理列表时发生冲突。稍后删除此临时扩展名。这意味着对每个文件进行一次重命名操作,对整个文件列表进行一次重命名操作。

文件名格式,文件数(仅限环境记忆)或文件名中的特殊字符没有要求。

@echo off
    setlocal enableextensions disabledelayedexpansion

    set "workingFolder=%~1"
    if not defined workingFolder set "workingFolder=%cd%"

    set "fileExtension=%~2"
    if not defined fileExtension set "fileExtension=*"

    call :randomizeFolderFiles "%workingFolder%" "%fileExtension%"

    endlocal
    exit /b

:randomizeFolderFiles folder fileExtension
    setlocal enableextensions disabledelayedexpansion 
    set "count=0"

    pushd "%~1"
    for /f "tokens=1,* delims=:" %%a in ('
        dir /b /a-d "*.%~2" 2^>nul ^| findstr /n "^"
    ') do ( set "f[%%a]=%%b" & set "count=%%a" & set "a[%%a]=%%a" )

    setlocal enabledelayedexpansion
    for /l %%a in (%count% -1 1) do (
        set /a "e=(!random! %% %%a)+1"
        set /a "t=a[!e!]"
        set /a "a[!e!]=a[%%a]"
        for %%c in (!t!) do ren "!f[%%a]!" "!f[%%c]!.$random"
    )
    endlocal
    if %count% gtr 0 ren "*.%~2.$random" "*."
    popd 

    endlocal & exit /b

f[]中的完整文件列表和a[]中的索引。数组a使用Fisher-Yates进行洗牌。在循环的每次迭代中,元素%%a(从%%a%count%的{​​{1}})与范围{{中的随机元素0交换1}},在!e!中留下该数组位置的最后一个元素。因此,将0..%%a(在原始列表中将位置%%a中的文件)重命名为f[%%a](随机播放中随机选择的文件)

已修改以适应评论

要将文件扩展名作为参数传递给批处理文件(或直接设置%%a变量中的值),只需要f[!e!]

fileExtension

或者,从代码中,

bmp

要使其在子目录中运行,doRandomize.cmd "c:\somewhere" "bmp" 行可以更改为

set "fileExtension=bmp"

也就是说,迭代文件夹列表,并为每个文件夹调用随机化过程。