Я рекомендую открыть командную строку, запустить for /?
и прочитать вывод справки сверху вниз. последней страницы. В четвертом абзаце уже написано, что в пакетном файле переменная цикла должна указываться с удвоением знака процента по сравнению с использованием команды FOR непосредственно в командной строке Windows.
Таким образом, решение может быть:
for %%F in (*.doc) do %1 -oice -nme "%%F" "%%~nF.docx"
Но я не могу рекомендовать использовать эту командную строку в пакетном файле по следующим причинам.
Причина 1 подробно объясняется в этом ответе в главе Проблема 7: Использование букв ADFNPSTXZadfnpstxz в качестве переменной цикла. Можно использовать эти буквы для переменной цикла, но лучше этого не делать. Существует множество других символов ASCII, не имеющих специального значения, которые всегда безопасно использовать в качестве переменной цикла.
Причина 2 заключается в том, что команда FOR ищет с *.doc
в текущем каталоге файлы с .doc
в длинном или в коротком имени файла. Таким образом, если каталог содержит Test1.doc
и Test2.docx
, ЗА запускает исполняемый файл конвертера с обоими именами файлов, как это видно при запуске в окне командной строки командной строки:
for %I in (*.doc) do @echo Long name: %I - short name: %~snxI
Вывод для каталога, содержащего Test1.doc
и Test2.docx
:
Long name: Test1.doc - short name: TEST1.DOC
Long name: Test2.docx - short name: TEST2~1.DOC
Причина 3 часто вызывает проблемы на дисках FAT32 и exFAT, но иногда возникает даже на дисках NTFS. FOR обращается к файловой системе при обработке файлов, соответствующих шаблону подстановки, после каждой итерации. В фоновом режиме выполняются _findfirst, _findnext, _findnext , ..., _findclose. Проблема заключается в том, что записи каталога изменяются из-за преобразования файлов Microsoft Word, поскольку файлы *.docx создаются в том же каталоге, что и обработанные файлы *.doc. Все файловые системы возвращают имена файлов, сохраненные в их таблице. Разница в том, что основная таблица файлов NTFS зависит от локали и сортируется по имени, в то время как таблица FAT32 и exFAT вообще не сортируется и поэтому резко меняется при каждом создании или удалении файла или папки в каталоге. По этой причине может случиться так, что некоторые файлы .doc
обрабатываются более одного раза, а другие пропускаются, что может привести даже к бесконечному циклу выполнения. Другими словами, поведение цикла FOR в этом случае не определено, поэтому цикл может работать случайно, но также может и не работать.
Решение использует командную строку:
for /F "delims=" %%I in ('%SystemRoot%\System32\where.exe *.doc 2^>nul') do %1 -oice -nme "%%I" "%%~dpnI.docx"
Проблемы 1 можно избежать, используя I
в качестве переменной цикла. Также можно было бы использовать #
или B
или J
и множество других символов ASCII.
FOR с параметром /F
и набором, заключенным в '
, приводит к запуску в фоновом режиме еще одного командного процесса с %ComSpec% /c
и командной строкой в '
, добавленными в качестве дополнительных аргументов. Поэтому он выполняется в фоновом режиме с Windows, установленной в C:\Windows
:
C:\Windows\System32\cmd.exe /c C:\Windows\System32\where.exe *.doc 2>nul
WHERE отличается от FOR или DIR. Он ищет только в длинном имени файла файлы с расширением .doc
. Таким образом, проблему 2 с сопоставлением файлов с расширением .docx
можно избежать, используя команду WHERE, которая выводит найденные файлы, соответствующие шаблону подстановочного знака с полным именем файла (диск + путь + имя + расширение).
Прочтите документацию Microsoft о Использование операторов перенаправления команд для объяснения 2>nul
. Оператор перенаправления >
должен быть экранирован символом вставки ^
в командной строке FOR, чтобы он интерпретировался как буквальный символ, когда интерпретатор команд Windows обрабатывает эту командную строку перед выполнением команды FOR, которая выполняет встроенная командная строка where
в отдельный командный процесс, запущенный в фоновом режиме.
Все, написанное where
для обработки STDOUT (стандартный вывод) запущенного фонового командного процесса, перехватывается cmd.exe
при обработке пакетного файла. Захваченные строки обрабатываются после запуска cmd.exe
и завершаются после завершения where.exe
. По этой причине проблема 3 исключена, поскольку список имен файлов с расширением файла .doc
больше не изменяется при выполнении преобразования. Список имен файлов уже полностью загружен в память cmd.exe
перед началом их обработки.
FOR с параметром /F
по умолчанию приводит к игнорированию пустых строк, разбиению каждой строки на подстроки с использованием обычного пробела и горизонтальной табуляции в качестве разделителей строк, игнорированию строки, если первая строка, разделенная пробелом/табуляцией, начинается с точки с запятой , а в противном случае назначение только первой строки, разделенной пробелом/табуляцией, указанной переменной цикла. Это поведение обработки строк по умолчанию здесь нежелательно, поскольку полные имена файлов могут содержать один или несколько пробелов. Строка параметра "delims="
определяет пустой список разделителей, что приводит к полному отключению поведения разделения строк. where
выводит имена файлов с полным путем, поэтому ни одна захваченная строка не может иметь ;
в начале, и по этой причине в этом случае можно сохранить неявное значение по умолчанию eol=;
. В противном случае при использовании другой командной строки, в результате чего захваченные строки будут просто именами файлов, соответствующими шаблону подстановки, eol=|
или eol=?
можно будет использовать, поскольку ни |
, ни ?
нельзя использовать в имени файла, чтобы избежать того, что файлы, имя которых начинается необычно с ;
игнорируются FOR.
Я предлагаю использовать следующий пакетный файл, который ищет wordconv.exe
, используя путь, хранящийся в реестре Windows для winword.exe
или excel.exe
или powerpnt.exe
, добавленный установщиком Office для Регистрация приложения при запуске без имени исполняемого файла.
@echo off
setlocal EnableExtensions DisableDelayedExpansion
goto Main
:GetConvertToolName
for %%# in (winword excel powerpnt) do (
for /F "skip=2 tokens=1,2*" %%I in ('%SystemRoot%\System32\reg.exe query "%~1\%%#.exe" /v Path') do (
if /I "%%I" == "Path" if exist "%%~K\wordconv.exe" for %%L in ("%%~K\wordconv.exe") do set "ConvertTool=%%~fL" & goto :EOF
)
)
goto :EOF
:Main
set "ConvertTool="
if not "%~1" == "" if exist "%~1" if /I "%~x1" == ".exe" set "ConvertTool=%~1"
if not defined ConvertTool call :GetConvertToolName "HKLM\Software\Microsoft\Windows\CurrentVersion\App Paths"
if not defined ConvertTool call :GetConvertToolName "HKCU\Software\Microsoft\Windows\CurrentVersion\App Paths"
if not defined ConvertTool (
echo ERROR: Failed to find the program wordconv.exe.
echo/
echo Please run %~nx0 with full name of wordconv.exe as argument.
echo/
pause
) else for /F "delims=" %%I in ('%SystemRoot%\System32\where.exe *.doc 2^>nul') do "%ConvertTool%" -oice -nme "%%I" "%%~dpnI.docx"
endlocal
Чтобы понять, какие команды используются и как они работают, откройте окно командной строки, выполните в нем следующие команды. , и очень внимательно прочитайте все страницы справки, отображаемые для каждой команды.
call /?
echo /?
endlocal /?
for /?
goto /?
if /?
pause /?
reg /?
reg query /?
set /?
setlocal /?
where /?
person
Mofi
schedule
02.12.2020