2

Я пытаюсь написать командный файл, который будет запускать exe всякий раз, когда в папке есть ровно 4 изображения JPG. После этого изображения должны быть удалены.

Кажется, он у меня работает, но файл запускает исполняемый файл снова и снова. Кажется, я не могу обернуться вокруг ошибки.

Любая помощь очень ценится!

@echo off
setlocal EnableDelayedExpansion
set counter=0

:loop
cd "c:\JPGfolder\"
for %%B in (*) do set /a counter+=1
echo File Count = !counter!

if !counter! EQU 4 (
for /f "delims=|" %%I in ('DIR "c:\JPGfolder\" /B /O:-D *.jpg') DO (
SET NewestFile=%%I
echo Newest File = "c:\JPGfolder\!NewestFile!"
start "" /w "c:\programs\generate.exe" "c:\JPGfolder\"%NewestFile%
del c:\JPGfolder\*.jpg
GOTO :BREAK
)
)

:BREAK
set /a counter=0

ping -n 2 localhost >nul

) else (
 echo No Files Found
 rem pause
 goto :loop
)
goto :loop

2 ответа2

5

Я вижу ряд проблем с вашим кодом. Но я не могу понять, как вы получаете поведение, которое вы описываете.

1) Вы считаете все файлы, но ваш код, чтобы получить самые новые и удалить все работает только с файлами .jpg. Ваш счет также должен быть ограничен .jpg файлами.

2) Вы забыли использовать отложенное расширение в своей строке СТАРТ. Но на самом деле нет необходимости использовать значение окружающей среды вообще. Вы можете просто использовать %%I напрямую, поэтому отсроченное расширение не требуется. Кроме того, весь путь к файлу должен быть заключен в кавычки.

3) У вас есть дополнительный ) который закрывает ваше заявление IF раньше. Строки ) ELSE ( и ) просто игнорируются, а промежуточные строки выполняются безоговорочно. Это странная причуда пакетного парсера. Если синтаксический анализатор ищет команду, и не существует блока открытых скобок, то ) и все после него в этой строке просто игнорируются.

4) Если вы исправите свои скобки, удалив одну из ) строк, то у вас все еще будет проблема, потому что вы ПОЛУЧИТЕ метку в сложном операторе IF. ЕСЛИ операторы ELSE нарушаются GOTO так же, как и операторы FOR /F. См. Https://stackoverflow.com/q/8481558/1012053 для получения дополнительной информации.

5) Ваш оператор CD должен использовать параметр /D, на случай, если вы находитесь на другом томе. Либо так, либо вместо этого используйте PUSHD.

6) Ваше сообщение "Файлы не найдены" неверно - в нем должно быть написано "Количество файлов <> 4"

7) Ваш алгоритм имеет фундаментальный недостаток. Что, если у вас есть 3 .jpg файла, когда ваш код сначала проверяется, а затем, когда он проверяет снова, есть 5 .jpg файлов? Ваш код никогда не увидит счет 4!

Также возможны некоторые упрощения.

8) Поскольку вы установили текущую директорию в «c:\JPGfolder», вам больше не нужно явно указывать путь к файлу каждый раз. Вы можете просто использовать %%~fI чтобы получить полный путь.

9) Я бы переместил инициализацию count ниже метки :LOOP . Тогда вам не нужно беспокоиться об установке значения в двух местах.

Я считаю, что следующая логика, которую вы пытались достичь. Имейте в виду, что это не относится к пункту 7).

@echo off
setlocal
cd /d "c:\JPGfolder\"

:loop
set counter=0
for %%B in (*.jpg) do set /a counter+=1
echo File Count = %counter%

if %counter% EQU 4 (
  for /f "delims=|" %%I in ('DIR *.jpg /B /O:-D') DO (
    echo Newest File = "%%~fI"
    start "" /w "c:\programs\generate.exe" "%%~fI"
    del *.jpg
    ping -n 2 localhost >nul
    goto :break
  )
) else (
  echo File count <> 4
)
:break
goto :loop

Вышесказанное можно упростить до:

@echo off
setlocal
cd /d "c:\JPGfolder\"

:loop
set counter=0
for %%B in (*.jpg) do set /a counter+=1
echo File Count = %counter%

if %counter% EQU 4 (
  for /f "delims=|" %%I in ('DIR *.jpg /B /O:-D') DO (
    echo Newest File = "%%~fI"
    start "" /w "c:\programs\generate.exe" "%%~fI"
    del *.jpg
    ping -n 2 localhost >nul
    goto :loop
  )
)
echo File count <> 4
goto :loop

Но на самом деле, вы, вероятно, должны вводить задержку на каждой итерации, независимо от того, было 4 файла .jpg или нет.

@echo off
setlocal
cd /d "c:\JPGfolder\"

:loop
set counter=0
for %%B in (*.jpg) do set /a counter+=1
echo File Count = %counter%

if %counter% EQU 4 (
  for /f "delims=|" %%I in ('DIR *.jpg /B /O:-D') DO (
    echo Newest File = "%%~fI"
    start "" /w "c:\programs\generate.exe" "%%~fI"
    del *.jpg
    goto :break
  )
) else (
  echo File count <> 4
)
:break
ping -n 2 localhost >nul
goto :loop

Я не буду использовать любой из приведенного выше кода из-за пункта 7). Я не могу решить это, потому что я не знаю, каково ваше намерение.

ОБНОВИТЬ

Мне кажется, что вы наблюдаете за папкой для файлов изображений, и вы хотите обрабатывать каждый четвертый какой-либо программой в хронологическом порядке. Все файлы удаляются после получения. Я рекомендую перемещать файлы, а не удалять их, на случай, если что-то пойдет не так, и вы захотите восстановить некоторые другие изображения. Вы всегда можете вручную удалить сохраненные файлы в любой момент.

Ваш текущий алгоритм требует, чтобы пакетный скрипт считывал и обрабатывал файлы быстрее, чем изображения, добавляемые в папку, в противном случае вы рискуете пропустить счет 4 и больше не обрабатывать изображения (мой пункт 7 сверху).

Ниже представлен новый алгоритм, который всегда работает, независимо от того, как быстро добавляются изображения.

Вместо того чтобы сбрасывать счетчик на 0 после каждого цикла, я позволяю счетчику расти бесконечно. Я использую арифметику по модулю, чтобы определить, когда файл представляет собой кратное 4 (по модулю результат равен 0). Я определяю значение по модулю 0, намеренно увеличивая деление на ноль ошибок, и || условно выполняет блок кода при ошибке.

@echo off
setlocal
cd /d "c:\JPGfolder"
md save 2>nul
set counter=0

:LOOP
for /f "delims=|" %%I in ('DIR *.jpg /B /O:-D') do (
  set /a "1/((counter+=1)%%4)" 2>nul || (
    echo Newest File = "%%~fI"
    start "" /w "c:\programs\generate.exe" "%%~fI"
  )
    move "%%I" save >nul
)
ping -n 2 localhost >nul
goto :LOOP

Ваш комментарий утверждает, что вы создаете коллаж из всех 4 изображений в каждой итерации. Я не понимаю, как это работает, когда вы передаете генерируемый файл только одно имя файла. Но если это действительно то, что происходит, то должен работать следующий альтернативный код:

@echo off
setlocal
cd /d "c:\JPGfolder"
2>nul (
  md save
  md working
  del working\*
)
set counter=0

:LOOP
for /f "delims=|" %%I in ('DIR *.jpg /B /O:-D') do (
  move "%%I" working >nul
  set /a "1/((counter+=1)%%4)" 2>nul || (
    echo Newest File = "%%~fI"
    start "" /w "c:\programs\generate.exe" "%%~dpIworking\%%~nxI"
    move working\* save >nul
  )
)
ping -n 2 localhost >nul
goto :LOOP
1

Ваша логика говорит: если counter = 4, то для каждого jpg в папке запускается exe.

Установка счетчика на 0 внутри цикла, после того как вы уже определили, что он равен 4, не будет останавливать цикл.

У вас также есть неполный оператор IF, вызванный дополнительной закрывающей скобкой (перед:BREAK), которая мешает вашему выражению ELSE.

Надеюсь, это поможет!

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .