【问题标题】:Windows batch file - Pick (up to) four random files in a folderWindows 批处理文件 - 在一个文件夹中选择(最多)四个随机文件
【发布时间】:2012-06-11 10:09:19
【问题描述】:

正如标题所说,我正在尝试从一个文件夹中选择最多四个随机文件(壁纸),以进行进一步处理。该文件夹不包含子文件夹,仅包含 *.jpg、*.bmp 和 *.png(它可能包含 Thumbs.db 文件,但我已经处理好了)。

我使用for 循环读取所有文件,制作类似于数组的内容,然后我想运行另一个for 循环来制作将充当索引的随机数以选择文件。

setlocal enabledelayedexpansion
set "wps=1 2 3 4"
set /a ind = 0

for /f "tokens=* delims=" %%g in ('dir C:\Wallpapers /a:-h-s /b /s') do (
    set /a ind += 1
    set "!ind!=%%g"
)

for %%g in (%wps%) do (
    set /a "num = (((!random! & 1) * 1073741824) + (!random! * 32768) + !random!) %% %ind% + 1"
    echo Wallpaper %%g is #!num! - Title: "!!num!!"
)


当然,回显的行只是输出Wallpaper 1 is #118 - Title: "118" 而不是Wallpaper 1 is #118 - Title: "C:\Wallpapers\Miami Skyline.jpg"

所以我的具体问题是:如何在 for 循环内双重展开变量?

[注意 #1:创建随机数的行需要很长,因为它提供了良好的随机值分布]
[注意 #2:我需要 wps 以这种方式存储,因为有时我可能只需要三张壁纸,不一定按数字顺序]

【问题讨论】:

    标签: random batch-file for-loop variable-expansion delayedvariableexpansion


    【解决方案1】:

    转移 !num! FOR 变量的值:-)

    for %%N in (!num!) do echo Wallpaper %%g is #%%N - Title: "!%%N!"
    

    一些额外的指针:

    • 如前所述,您的 DIR 命令包括文件夹。您需要添加/A-D 选项

      dir C:\Wallpapers /a:-h-s-d /b /s

    • 您的数字变量名称适用于您现有的代码。但是,如果您尝试使用正常扩展来访问它们,您将会遇到麻烦,因为%1% 将作为第一个批处理参数而不是环境变量进行扩展。在一般实践中,您应该避免以数字开头的环境变量。你可以使用:

      set wp!ind!=%%g
      ...
      echo Wallpaper %%g is #!num! - Title: "!wp%%N!

    • 您可以通过在循环底部而不是顶部递增计数器来使数组基于 0。然后你不需要在你的随机数上加一。 (这个技巧很简单。更多的是风格问题。)

    • 您不需要"tokens=*""delims="。我推荐后者。 "delims=" 将保留整个字符串。 tokens=* 将保留整个字符串 after 它去除前导空格和制表符。文件名可以以空格开头。

    • 如果任何文件名包含! 字符,您的代码将失败。在%%g 的扩展过程中,由于扩展延迟,感叹号将被破坏。通过打开和关闭延迟扩展并使用 FOR 变量跨 ENDLOCAL 屏障传输值,这很容易解决。

    这是包含所有建议的代码

    @echo off
    setlocal disableDelayedExpansion
    set "wps=1 2 3 4"
    set /a ind = 0
    
    for /f "tokens=* delims=" %%g in ('dir C:\Wallpapers /a:-h-s-d /b /s') do (
      setlocal enableDelayedExpansion
      for %%N in (!ind!) do (
        endlocal
        set "wp%%N=%%g"
      )
      set /a ind += 1
    )
    
    setlocal enableDelayedExpansion
    for %%g in (%wps%) do (
      set /a "num = (((!random! & 1) * 1073741824) + (!random! * 32768) + !random!) %% %ind%"
      for %%N in (!num!) do echo Wallpaper %%g is #%%N - Title: "!wp%%N!"
    )
    

    【讨论】:

    • 感谢您的建议和最终代码,帮助很大,一切都非常清楚。请注意:第一行setlocal disableDelayedExpansion(第二行)可以省略,对吧?另外,我更喜欢有一个从 1 开始的数组,因为我的文件管理器从 1 开始编号文件。然后第一个 for 循环读取for /f "tokens=* delims=" %%g in ('dir C:\Dati\Marco\Documenti\ /a:d /b') do ( set /a ind += 1 setlocal enableDelayedExpansion for %%N in (!ind!) do ( endlocal set "wp%%N=%%g" ) )(注意设置 ind 和延迟扩展的交换)
    【解决方案2】:

    您可以像 dbenham 建议的那样使用另一个 FOR,也可以使用 CALL

    call echo Wallpaper %%g is #!num! - Title: "%%!num!%%"
    

    CALL 再次扩展一行,但在第二次重新解析该行时,只有百分比扩展、延迟扩展和 FOR 循环扩展都不起作用。

    编辑:这仅适用于 num 的内容不以数字开头的情况。

    但您可以使用cmd /c 进行第二次扩展,然后它也适用于数字名称。

    cmd /c echo Wallpaper %%g is #!num! - Title: "%%!num!%%"
    

    【讨论】:

    • 除非它会因为变量名是数字而失败!显然,名称应该更改为包含字母前缀。
    • 是的,你是对的,我错过了,但你可以用 cmd /c 解决它
    猜你喜欢
    • 2011-07-29
    • 1970-01-01
    • 2017-09-13
    • 2019-12-28
    • 1970-01-01
    • 2018-12-31
    • 1970-01-01
    • 1970-01-01
    • 2016-12-30
    相关资源
    最近更新 更多