Пакетный файл Windows — выберите (до) четыре случайных файла в папке

Как следует из названия, я пытаюсь выбрать до четырех случайных файлов (обоев) из папки для дальнейшей обработки. Папка не содержит вложенных папок, только *.jpg, *.bmp и *.png (она может содержать файл Thumbs.db, но я уже позаботился об этом).
< br/> Я читаю все файлы с помощью цикла 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 хранилось таким образом, потому что иногда мне может понадобиться всего три обои, не обязательно в порядке номеров]


person Marco    schedule 11.06.2012    source источник


Ответы (2)


Перенесите !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% будет расширяться как 1-й пакетный аргумент вместо переменной среды. В общем случае вам следует избегать начинать переменную среды с числа. Вы можете использовать:

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

  • Вы можете сделать свой массив 0 основанным, увеличив свой счетчик в нижней части цикла, а не в верхней части. Тогда вам не нужно добавлять его к вашему случайному номеру. (Этот совет тривиален. Скорее вопрос стиля.)

  • Вам не нужны оба "tokens=*" и "delims=". Я рекомендую последнее. "delims=" сохранит всю строку. tokens=* сохранит всю строку после удаления начальных пробелов и знаков табуляции. Имя файла может начинаться с пробелов.

  • Ваш код не будет работать, если любое из имен файлов содержит ! символов. Восклицательный знак будет поврежден во время расширения %%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!"
)
person dbenham    schedule 11.06.2012
comment
Спасибо за предложения и окончательный код, очень помогает, и все кристально ясно. Одно замечание: первую 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 и delayedexpansion) - person Marco; 11.06.2012

Вы можете использовать другой FOR, как предложил dbenham, или вы можете использовать CALL

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

CALL расширяет строку во второй раз, но только процентное расширение, ни отложенное расширение, ни расширение цикла FOR не работает во второй повторной обработке строки.

EDIT: Это работает, только если содержимое num не начинается с числа.

Но вы можете использовать cmd /c для расширения во второй раз, тогда он будет работать и с числовыми именами.

cmd /c echo Wallpaper %%g is #!num! - Title: "%%!num!%%"
person jeb    schedule 11.06.2012
comment
За исключением того, что это не удастся, потому что имя переменной числовое! Очевидно, что имена должны быть изменены, чтобы включить префикс альфа. - person dbenham; 11.06.2012
comment
Да, вы правы, я пропустил это, но вы могли бы решить это с помощью cmd /c тогда - person jeb; 11.06.2012