Хорошо, на первый взгляд я вижу пять шесть семь (с половиной) явных ошибок здесь:
1.Кавычки вокруг аргументов echo
.
echo
являются встроенной оболочкой, и их синтаксис был довольно фиксирован 25 лет назад в DOS и CP / M.echo
просто печатает все, что идет после него, до конца команды (это могут быть такие вещи, как разрыв строки, )
, &
, |
и т. Д.), Поэтому вам нужно:
echo Starting blur detection ...
и
echo blurDetection %i of %num%
2.Пробелы вокруг знака равенства в set
.
set
, как и echo
- встроенная оболочка.Его синтаксис также немного неудобен (хотя у вас есть такая же проблема и в некоторых оболочках Unix).Дело в том, что все между set
и знаком равенства - это имя переменной, все после нее - это значение.В этом случае это означает, что имя вашей переменной заканчивается пробелом , а значение начинается с пробела .Поэтому, что бы вы ни делали, никогда не ставьте пробелы вокруг знака равенства.Язык командного процессора не слишком прост в использовании пробелов в отличие от многих других языков программирования.Поэтому:
set foo=bar
, а не
set foo = bar
, иначе вы никогда не найдете переменную с именем foo
, потому что вам нужно будет использовать %foo %
(обратите внимание на пробел).
3.set
не выполняет арифметику, пока вы не скажете это.
set
не вычислит ничего, если вы явно не скажете это.Это делается с помощью set /a
:
Переключатель /A
указывает, что строка справа от знака равенства является числовым выражением, которое оценивается.
Поэтому вам нужно
set /a num=tempnum - 5
С /a
%
вокруг имен переменных можно опустить с правой стороны, что делает код немного более понятным, обычно.
4.set
только устанавливает значения, он не выполняет никакого кода.
В
set tempnum=dir root | find /i "file"
вы, очевидно, пытаетесь установить переменную на основе вывода некоторыхкоманда.Это не может работать, так как это просто устанавливает tempnum
в dir root
и отправляет вывод этой команды (нет) в find
из-за канала.Я не совсем уверен, что это должно делать, но я предполагаю, что вы подсчитываете файлы.
Как правило, вы не должны полагаться на специфический для локали вывод команд, чтобы выполнить что-то, поскольку это ломаетдовольно легко.Особенно, если вы хотите запускать пакетные файлы на других компьютерах, кроме вашего (но даже в этом случае вы можете столкнуться с проблемами).Для подсчета файлов вы можете перебирать файлы и просто считать, сколько вы встречаете.Оператор for
может выполнять итерации по файлам следующим образом:
set num=0
for %%f in (%root%\*) do set /a num+=1
Обратите внимание, что я предполагаю, что %root%
- это каталог, файлы которого вас интересуют. Хотя вы ранее использовали %root%
.Если вам повезет, %root%
- это просто root
, иначе ваш код никогда не сможет правильно работать.
Поскольку вы, очевидно, хотите вычесть 5 для некоторых файлов, которые не являются частью того, что вам нужно, вы можете сделать
set /a num-=5
впоследствии.Другой вариант, если файлы, которые вас интересуют, имеют общую черту, состоял бы в том, чтобы ограничить шаблон таким, например,
for %%f in (%root%\*.tif) do set /a num+=1
, чтобы вам не нужно было вычитать что-то из окончательного числа.
5.for
переменные только однобуквенные.
Самая большая из них здесь, вероятно, на которую уже указывал STATUS_ACCESS_DENIED : переменные, используемые в операторах for
, являются специальными.Они не являются переменными окружения и состоят только из одной буквы.Поэтому код должен читать
for /l %%i in ...
6.for
переменные должны начинаться с префикса двух знаков процента в пакетных файлах.
В командной строке оператор for
, такой как
for /l %x in (1,1,5) do @echo %x
просто отлично, но в пакетных файлах синтаксический анализатор будет спотыкаться об этом, вероятно, ожидая аргумента для программы (это %1
, %2
и т. Д.).Как уже указано в документации к for
, внутри пакетных файлов переменные должны использовать два %
:
for /l %%x in (1,1,5) do @echo %%x
Это, в свою очередь, сломается при использовании непосредственно в командной строке. TANSTAAFL .
Однако это не относится к переменным среды.Там нет удвоения знаков процента (см. Также ниже).
Также обратите внимание, что у вас есть другая ошибка в пакете во второй строке, где вы используете idx
как переменную среды, даже если выпопробуйте использовать его как переменную for
в другом месте:
%root%\%img%__%idx%.tif
должно читать
%root%\%img%__%%i.tif
7.Переменные окружения должны быть окружены %
.
Строка
for /l %i in (0, 1, num) do ...
никогда не будет работать и, вероятно, будет жаловаться на неожиданность num
.Чтобы получить значение переменной окружения, вам нужно заключить его в знаки процента:
for /l %%i in (0, 1, %num%) do ...
в противном случае это просто строка.
В аналогичном ключе это также относится и к окончательному echo
.%%i
- это переменная for
, поэтому только префикс, но num
- это переменная окружения, поэтому ее необходимо заключить в %
:
echo blurDetection %%i of %num%
Иногда это может сбивать с толку,но, к счастью, мы еще не рассматривали отложенное расширение: -).
И последнее, хотя и незначительное:
8.Всегда заключайте в кавычки имена файлов.
В вашем случае весь пакет сломается, как только %root%
содержит путь с пробелами.Это начинается во второй строке, где вы ищите существующий каталог.Сделайте это более надежным, заключив путь в пробелы:
if not exist "%root%\output" mkdir output
То же самое с вызовами внутри цикла:
"%root%\blurDetection.exe" "%root%\%img%__%%i.tif" "%root%\output"
Вы ничего не нарушаете, когда в пробеле нет пробеловимя файла, но если оно есть, оно просто работает, как и ожидалось.
Теперь, когда мы это получили, мы можем посмотреть, как выглядит ваша партия:
echo Starting blur detection ...
if not exist "%root%\output" mkdir "%root%\output%"
set num=0
for %%f in (%root%\*.tif) do set /a num+=1
for /l %%i in (0, 1, %num%) do (
"%root%\blurDetection.exe" "%root%\%img%__%%i.tif" "%root%\output"
echo blurDetection %%i of %num%
)
Это должно, по крайней мере, сработать и, вероятно, является довольно точным воспроизведением того, о чем вы думали, и я бы резюмировал:
- Создать выходной каталог, если он еще не существует
- Найдите количество изображений для обработки (которые называются последовательно)
- Обработайте их и напечатайте вывод состояния.
Но мы еще не закончили.Как вы заметили в приведенных выше объяснениях, for
уже может перебирать файлы.С шагами 2 и 3 мы дважды перебираем набор изображений, что не совсем необходимо.Все, что требуется, - это один цикл и некоторые изменения:
for %%f in (%root%\%img%__*.tif) do "%root%\blurDetection.exe" "%%f" "%root%\output"
Но теперь мы пропускаем вывод статуса.И файлы больше не обрабатываются по порядку (что может или не может быть проблемой; я предполагаю, что это не так).Если вам отчаянно не нужно сообщение «Обработанный файл», то подойдет следующее:
for %%f in (%root%\%img%__*.tif) do (
"%root%\blurDetection.exe" "%%f" "%root%\output"
echo blurDetection %%~nf
)
, которое просто выводит последнее обработанное имя файла, но все равно будет обрабатывать изображения в порядке 1
, 10
, 11
, ..., 19
, 2
, 20
... поэтому число, скорее всего, не совсем точно соответствует прогрессу.Если вам нужен счетчик, то вам снова нужен цикл из предыдущего, который подсчитывает файлы.Я думаю, что я оставляю это сейчас как есть.
Несколько вещей, которые мне показались любопытными:
- Ни
root
, ни img
нигде не определены.Я предполагаю, что это всего лишь фрагмент из более крупной программы, но читателю нехорошо наткнуться на переменные, которые не имеют видимой инициализации. - Хотя
%root%
используется во многих местах,текущий рабочий каталог кажется идентичным (строка 2, где вы проверяете наличие %root%\output
и, если нет, создаете просто output
. Вероятно, pushd
в начале и popd
в конце будет более чистымспособ обработки этого. - Вы утверждаете, что заключили в кавычки сообщение об ошибке PowerShell, но это сообщение об ошибке
cmd
. Если вы запустили этот сценарий через PowerShell, он уже умрет во второй строке.
Другое дело, поскольку вы упомянули, что это должно работать на Server 2008 R2: PowerShell установлен там по умолчанию, и если ваша политика выполнения установлена правильно, вы также можете сделать это с помощью сценария PowerShell:
Write-Host Starting blur detection ...
if (!(Test-Path $root\output)) { New-Item -ItemType Directory $root\output }
$files = Get-ChildItem $root\*.tif
$files | ForEach-Object { $i = 1 } {
& "$root\blurDetection.exe" $_ $root\output
Write-Host blurDetection ($i++) of ($files.Count)
}