我有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命令提示符和批处理文件完成?
由于
答案 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"
也就是说,迭代文件夹列表,并为每个文件夹调用随机化过程。