Почему "..." не распознается как внутренняя или внешняя команда, работающая программа или командный файл?

У меня есть однострочный фрагмент кода, который отлично работает в командной строке, но дает сбой и выдает ошибки, когда я запускаю его как часть пакетного сценария.

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

for /f "delims=" %d in ('dir /s /b /ad ^| sort /r') do rd "%d"

Однако, когда положить в пакетный файл, как это...

FOR /f "delims=" %%d in ('dir /s /b /ad ^| sort /r') do rd "%%d"

... выдает стандартную ошибку: Sort is not recognised as an internal or external command...

В течение последнего часа я экспериментировал с и без выхода из канала, изменяя порядок опций, просматривая документацию обоих dir а также sortи т. д., но я до сих пор не смог понять, что здесь происходит. Остальная часть командного файла, которая состоит всего из нескольких строк, работает нормально, и это единственная строка в ней, которая дает сбой.

Кто-нибудь может помочь? Заранее спасибо, я очень ценю это.

4 ответа

Решение

А) Как интерпретатор команд Windows ищет команды?

Интерпретатор команд Windows ищет КОМАНДУ для выполнения которой

  1. не является внутренней командой cmd.exe а также
  2. просто указывается с именем файла без расширения файла и без пути

для файла, соответствующего шаблону command.* и имеющий расширение файла, указанное в локальной переменной среды PATHEXT

  1. первый в текущем каталоге и
  2. следующий во всех каталогах локальной переменной среды PATH,

SORT и FIND, FINDSTR, ROBOCOPY и XCOPY и многие другие команды не являются внутренними командами cmd.exe, Это консольные приложения, установленные с Windows, расположенные в каталоге %SystemRoot%\System32 имея имя файла sort.exe, find.exe, findstr.exe, robocopy.exe, xcopy.exe...

Такие консольные приложения, доступные по умолчанию в Windows, называются внешними командами, чтобы лучше отличать их от консольных приложений, не установленных в операционной системе Windows.


Б) Как определяется переменная среды PATH?

Есть 3 типа PATH переменные:

  1. система PATH который используется для всех учетных записей и хранится в реестре Windows под ключом:

    HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment
    
  2. пользователь PATH который используется только для текущей учетной записи и хранится в реестре Windows под ключом:

    HKEY_CURRENT_USER\Environment
    
  3. Местный PATH который всегда является копией местного PATH родительского процесса, который запустил текущий процесс.

Windows объединяет систему и пользователя PATH к местному PATH для экземпляра Windows Explorer, используемого в качестве рабочего стола Windows, с ярлыками на экране рабочего стола и меню "Пуск" Windows в качестве видимого интерфейса для пользователя.

При запуске нового процесса вся текущая активная таблица переменных среды запущенного процесса копируется Windows для нового процесса.

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

Это означает, что когда-то процесс, как cmd.exe был запущен для выполнения командного файла, у процесса есть собственный набор переменных среды, которые может изменять только сам процесс. Ни один другой процесс не может изменить переменные среды уже запущенного процесса.


C) Что означает сообщение об ошибке?

Сообщение об ошибке

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

всегда означает, что

  1. имя файла

    • консольное приложение
    • Приложение с графическим интерфейсом
    • скрипт (командный файл, скрипт PowerShell, скрипт Perl, VBScript, JScript, ...)


    был указан для выполнения, скорее всего, без расширения файла и без (полного) пути к файлу исполняемого файла / скрипта и

  2. Windows не удалось найти файл, соответствующий шаблону FileName.* с расширением файла, указанным в текущей активной переменной среды PATHEXT в текущем каталоге или любом другом каталоге в текущей активной переменной среды PATH,


D) Каковы возможные причины этого сообщения об ошибке?

Типичные причины:

1. Имя файла для выполнения было указано неверно из-за ошибки при вводе.

Проверять посимвольно название команды / исполняемого файла.

2. Текущий каталог отличается от каталога, содержащего файл для выполнения.

Бежать echo Current directory is: %CD% в командной строке или добавьте эту строку в командный файл над командной строкой, которая не видит текущий каталог.

3. Исполняемый файл или скрипт для запуска не установлены вообще.

Проверьте наличие исполняемого файла для запуска. Некоторые установочные пакеты работают, только если ранее были установлены другие пакеты, такие как Java, NPM, PHP и т. Д.

4. Каталог файла для выполнения не находится в PATH совсем.

Откройте в панели управления Windows окно "Настройки системы", нажмите " Дополнительные параметры системы" слева, нажмите кнопку " Переменные среды" и найдите в обоих списках Path и их ценности. По умолчанию Path существует только в списке системных переменных.

5. Работающий процесс / приложение не было перезапущено после модификации системы или пользователя PATH ,

Модификация системы PATH или пользователь PATH с командой setx или через Панель управления - Система - Расширенные настройки системы были выполнены пользователем или установщиком, но уже запущенный процесс / приложение, такое как открытая командная строка или окно PowerShell, не было закрыто / закрыто и открыто / перезапущено после PATH модификация. Это необходимо, как подробно описано в главе F ниже.

6. ЛОКАЛЬНАЯ переменная PATH был изменен ранее в командной строке или в командном файле.

Бежать set path в командной строке или добавьте эту команду в командный файл над командной строкой, который не видит текущие значения переменных среды PATH а также PATHEXT,

Последняя причина связана с тем, что внешняя команда SORT не найдена при выполнении командного файла, который находится где-то выше set path=...,


E) Как избежать этого сообщения об ошибке?

Лучше всего кодировать пакетный файл для независимости от PATH а также PATHEXT и порядок каталогов в PATH что означает здесь использование командной строки:

FOR /f "delims=" %%d in ('dir /s /b /ad ^| %SystemRoot%\System32\sort.exe /r') do rd "%%d"

Любая внешняя команда, чей исполняемый файл хранится в %SystemRoot%\System32 должен быть указан в командном файле с этим путем и с расширением файла .exe, Тогда интерпретатору команд Windows не нужно искать файл, используя локальный PATH а также PATHEXT и пакетный файл работает всегда (пока переменная окружения SystemRoot также не изменяется в командном файле, который я никогда не видел).


F) Когда системное или пользовательское изменение PATH применяется к процессам?

Когда пользователь открывает окно командной строки через меню Пуск Windows или из окна Windows Explorer, пользователь запускает cmd.exe с неявной опцией использования /K держать окно консоли открытым после завершения команды, которая подходит для отладки командного файла.

При двойном щелчке командного файла в проводнике Windows запускается пользователь cmd.exe для обработки командного файла с неявным использованием опции /C закрыть окно консоли после завершения пакетной обработки, что не подходит для отладки пакетного файла, поскольку сообщения об ошибках в этом случае не отображаются.

В обоих случаях Windows создает копию переменных среды запуска приложения cmd.exe который обычно Windows Explorer. Поэтому запущенный командный процесс имеет локальный PATH значение которого совпадает со значением родительского процесса при запуске cmd.exe,

Пример:

  1. Откройте окно командной строки, запустите title Process1 и беги set path,
    Выход PATH а также PATHEXT как в настоящее время определено для текущей учетной записи пользователя в окне консоли, имеющем теперь заголовок окна Process1.

  2. Бежать set PATH=%SystemRoot%\System32 и следующий раз set path,
    Выход снова PATH а также PATHEXT, но с PATH содержащий только один каталог сейчас.

  3. Бежать start "Process2" и запустите в новом окне консоли с заголовком окна Process2 команду set path,
    Выход PATH а также PATHEXT с теми же значениями, что и раньше в Process1.
    Это демонстрирует, что при запуске нового процесса текущие переменные среды выполняющегося процесса копируются, а не то, что сама Windows в настоящее время хранит в реестре Windows.

  4. Запустите в Process2 команду set PATH= и следующий set path,
    Выход только PATHEXT потому что местный PATH больше не существует для Process2.
    Это демонстрирует, что каждый процесс может изменять свои переменные среды, включая полное удаление.

  5. Переключиться в окно Process1, запустить команду set PATH=%PATH%;%SystemRoot% и следующий set path,
    Выход PATH с двумя каталогами и PATHEXT,

  6. Запустите команду start "Process3" и в открывшемся окне с названием Process3 команда set path,
    Выход PATH с двумя каталогами, как определено также для Process1 и PATHEXT,

  7. Запустите в Process3 команду set PATH=%SystemRoot%\System32,

Есть 3 командных процесса, выполняющихся со следующими значениями для локального PATH когда %SystemRoot% расширяется до C:\Windows:

Процесс1: PATH=C:\Windows\System32;C:\Windows
Процесс2: PATH не существует вообще.
Процесс3: PATH=C:\Windows\System32

Итак, что теперь происходит при открытии Панели управления - Система - Дополнительные параметры системы - Переменные среды и добавлении в список пользовательских переменных новой переменной среды PATH со значением C:\Tempили в случае, если уже есть пользователь PATH переменная окружения, редактировать PATH и добавить ;C:\Temp к стоимости?

Что ж, до тех пор, пока открыто диалоговое окно с заголовком Переменные среды, показывающее два списка, ничего не происходит при изменении переменных, пока не будет нажата кнопка ОК, чтобы перенести все изменения в реестр Windows и закрыть окно.

Давайте вернемся к 3 запущенным командным процессам и запустим в Process1, Process2 и Process3 команду set path, Это можно увидеть:

Процесс1: PATH=C:\Windows\System32;C:\Windows
Процесс2: PATH не существует вообще.
Процесс3: PATH=C:\Windows\System32

Ничего не изменилось на уже запущенных процессах.

Ни один процесс не может изменить переменные среды запущенного процесса.

Откройте в главном меню Windows еще одно окно командной строки и выполните в четвертой командной строке команду set path, Видно, что местный PATH четвертого командного процесса добавил каталог C:\Temp сейчас.

Затем закройте все 4 командных процесса и удалите добавленного пользователя. PATH соответственно удалить ;C:\Temp от пользователя PATH добавив этот путь к каталогу раньше.

Как это возможно, если ни один процесс не может изменить переменные среды уже запущенного процесса?

Как был изменен список переменных среды экземпляра Windows Explorer, работающего в качестве рабочего стола Windows, при закрытии окна переменных среды кнопкой OK?

Ответ на эти два вопроса дал eryksun в своем комментарии.

После внесения изменений в системные и пользовательские переменные в реестр при нажатии кнопки " ОК" в окне " Переменные среды" Windows отправляет сообщение WM_SETTINGCHANGE всем окнам верхнего уровня, чтобы информировать запущенные приложения об измененных системных параметрах.

Это зависит от приложения, обрабатывается ли это сообщение о событии и как. Проводник Windows, работающий как рабочий стол Windows, считывает переменные среды из реестра и соответствующим образом обновляет свой список переменных среды. Другие приложения, такие как Total Commander, также обрабатывают это сообщение и обновляют свои списки переменных среды. Но cmd.exe не делает это к счастью, поскольку это было бы действительно проблематично.

Есть ли возможность изменить системную или пользовательскую переменную с уведомлением через WM_SETTINGCHANGE из окна командной строки или командного файла?

Можно изменить значение реестра переменной среды, используя reg add команда. Но это не приводит к отправке WM_SETTINGCHANGE сообщение для всех окон верхнего уровня. Такие изменения сделаны с reg add или с regedit потребовать перезагрузки Windows (или, по крайней мере, выйти из системы и войти в систему текущего пользователя), чтобы принять во внимание вообще.

Но есть и команда setx который предназначен для изменения системной или пользовательской переменной и который также отправляет WM_SETTINGCHANGE сообщение всем окнам верхнего уровня после обновления реестра в соответствии с заданными аргументами. Бежать setx /? в окне командной строки для деталей. Но, пожалуйста, примите во внимание, что setx не изменяет локальную переменную среды запущенного командного процесса. Это должно быть сделано с помощью команды set используется в дополнение к setx,


G) Как переменная окружения PATHEXT обрабатывается Windows?

Переменная среды PATHEXT со списком расширений файлов в Windows обрабатывается иначе, чем в переменной окружения PATH,

система PATHEXT и пользователь PATHEXT НЕ связаны с местными PATHEXT,

Пользователь PATHEXT заменяет систему PATHEXT для всех процессов, запущенных в среде учетной записи, имеющей пользователя PATHEXT определены.

Там определена только система PATHEXT переменная окружения по умолчанию.


H) Можно ли отключить поиск файлов в текущем каталоге?

Командный процессор Windows выполняет поиск в текущем каталоге по умолчанию, если в командной строке или в пакетном файле указано имя файла сценария или исполняемого файла без пути, что означает отсутствие обратной косой черты. \ (или косая черта / благодаря автокоррекции) в строке аргумента.

Но в Windows Vista и более поздних версиях клиента Windows, а также в Windows Server 2003 и более поздних версиях сервера Windows действительно возможно отключить поиск сценария / исполняемого файла в текущем каталоге, указанном без хотя бы относительного пути .\ путем определения переменной среды NoDefaultCurrentDirectoryInExePath с любым значением, написанным eryksun в его комментарии ниже и объясненным Microsoft в статье MSDN о функции NeedCurrentDirectoryForExePath.

См. Удаление текущего рабочего каталога из пути для получения дополнительной информации об использовании этой переменной среды.

Скорее всего, вы возились с PATH переменная. Возможно, вы переписываете это где-то еще в вашем сценарии. поскольку sort это внешняя команда, в отличие от всех остальных в вашей командной строке, как for, dir, rd, которые cmdвнутренние команды, PATH переменная необходима для поиска команды. Если PATH не определено, внешние команды ищутся только в текущем рабочем каталоге. Также есть PATHEXT переменная, необходимая для определения стандартных расширений файлов для исполняемых файлов, например .com, .exe, Так когда sort появляется в командной строке или в пакетном файле, система ищет текущий рабочий каталог и все каталоги, указанные PATH переменная для файла с базовым именем sort и одно из расширений, указанных PATHEXT, Команда sort на самом деле называется sort.exe и обычно находится в C:\Windows\System32,

В моем случае я был настолько уверен, что не связывался с . Это было то, что я не знал, чтоpathиPATHодинаковы. CMD нечувствителен к регистру.

Этот ответ содержит дополнительную информацию к моему первому ответу здесь относительно ограничений длины файлов .

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

Максимальная длина локального строкового значения зависит от версии Windows и нескольких ограничений длины строки.


Ограничения длины PATH в Windows Vista и Windows 7

Ограничения длины системного PATH

Система , хранящаяся в реестре Windows, усекается до максимальной длины символов перед расширением всех ссылок на переменные среды. Усеченная строка, назначенная локальному из, также может быть короче, чем символы в системе , содержит ссылки на переменные среды, такие как (12 символов), расширяющиеся до (10 символов), и ни один пользователь не хранится в реестре Windows.

Система усекается до максимальной длины символов после расширения ссылок на переменные среды. Усеченная строка, назначенная локальному из, может быть длиннее, чем строковое значение, хранящееся в реестре Windows, если ссылки на переменные среды расширяются до строк, которые длиннее, чем строки ссылок на переменные среды.

В худшем случае система дважды усекается до максимальной длины символов, первый раз до и второй раз после расширения ссылок на переменные среды.

Ограничения длины пользовательского PATH

Пользователь полностью игнорируется независимо от длины системы , если строковое значение, хранящееся в реестре Windows , длиннее символов.

Пользователь добавляется с дополнительной точкой с запятой в расширенной форме к локальному или находящемуся в реестре Windows не длиннее символов, даже если пользователь находится в расширенной форме длиннее символов из-за ссылок на переменные среды, такие как,или.

Локальный из может достигать максимальной длины символов в худшем случае при очень длинной и возможно уже раз или два обрезанной системе и юзере не длиннее символов в реестре Windows, но длиннее символов в развернутом виде.

Командный процессор Windows перестает находить какие-либо исполняемые файлы на локальном компьютере , становится слишком длинным, например, если система из 4095 символов в реестре расширяется до строки из 4087 символов и объединяется с точкой с запятой, а пользователь хранится в реестре Windows с 4074 символами, но расширен до строкового значения длиной 4104 символа, в результате чего получается локальный с общей длиной символов. Там даже не найден ни один исполняемый файл вв локальном строковом значении имеет длину символов, хотя выполнение выводит локальное значение с первым путем к каталогу.

Существует ограничение строки командной строки командной строки (Cmd. exe), что означает, что имя переменной среды плюс знак равенстваплюс значение переменной строки плюс завершающий нулевой байт строки должны вписываться в массив символовперсонажи. По этой причине строковое значение локальной переменной среды, выводимое при запуске в окне командной строки, не может быть длиннее символов, хотя в памяти строковое значение локальной может быть доперсонажи.

Внутренняя команда SET of больше не выводит перевод строки при запускев окне командной строки, если локальный имеет строковое значениеили более символов. В окне консоли отображается по этой причине в данном случае переменная окружениясо знаком равенства и его строковым значением, добавленным в конец строкового значения переменной среды.

Ограничения длины окон Панели управления для редактирования переменных среды

Пользовательская , системная или любая другая постоянная хранимая переменная среды в реестре Windows со строковым значением, длина которого превышает количество символов, не отображается в диалоговом окне « Переменные среды» . Для пользователя это выглядит так, как будто не существует переменной среды, которая имеет строковое значение, состоящее из более чем символов, хотя переменная среды хранится в реестре и, возможно, даже определена в локальной среде запущенных процессов . Другие пользовательские и системные переменные по-прежнему отображаются в окне «Переменные среды» .

В диалоговых окнах « Редактировать пользовательскую переменную» и «Редактировать системную переменную» отображается значение переменной , содержащее не более символов. Пользователь может удалить символы из такого длинного строкового значения и сохранить сокращенное строковое значение. Но пользователь не может добавлять символы или заменять существующие символы, если строковое значение переменной среды длиннее символов. По этой причине пользователь может редактировать пользовательскую или системную переменную среды со строковым значением, превышающим символы, только для удаления пути к каталогу с помощью окна «Переменные среды» панели управления ., но не для изменения символов существующего пути к каталогу или добавления еще одного пути к каталогу в строку переменной среды, которая длиннее символов.

Рекомендации по длине PATH

Система и пользователь , хранящиеся в реестре Windows и в развернутом виде , не должны быть длиннеесимволы в Windows Vista и Windows 7 и лучше всего короче, чемсимволов для редактирования в окнах панели управления .


Ограничения длины PATH в Windows XP

Ограничения длины системного PATH

Система , хранящаяся в реестре Windows, усекается до максимальной длины символов перед расширением всех ссылок на переменные среды. Усеченная строка, назначенная локальному из, также может быть короче символов в системе , содержащей ссылки на переменные среды, такие как(12 символов) расширяется до(10 символов) и ни один пользователь не сохранен в реестре Windows.

Система усекается до максимальной длины символов после расширения ссылок на переменные среды. Усеченная строка, назначенная локальному изможет быть длиннее строкового значения, хранящегося в реестре Windows, если ссылки на переменные среды расширяются до строк, которые длиннее, чем строки ссылок на переменные среды.

В худшем случае система дважды усекается до максимальной длины символов, первый раз до и второй раз после расширения ссылок на переменные среды.

Ограничения длины пользовательского PATH

Пользователь полностью игнорируется, если расширенная система , объединенная с расширенным пользователем с дополнительной вставленной точкой с запятой, приводит к строковому значению, превышающему количество символов . Поэтому максимальная длина пользователя в Windows XP зависит от текущей длины развернутой системы .

Ограничения длины окон Панели управления для редактирования переменных среды

Пользовательская , системная или любая другая постоянная хранимая переменная среды в реестре Windows со строковым значением, длина которого превышает количество символов, не отображается в диалоговом окне « Переменные среды» . Для пользователя это выглядит так, как будто не существует переменной среды, которая имеет строковое значение болеесимволов, хотя переменная среды хранится в реестре и, возможно, даже определена усеченной в локальной среде запущенных процессов. Другие пользовательские и системные переменные по-прежнему отображаются в окне «Переменные среды» .

В диалоговых окнах « Редактировать пользовательскую переменную» и «Редактировать системную переменную» отображается значение переменной , содержащее не более символов. Пользователь может отредактировать еще более длинное строковое значение и сохранить строковое значение, но строковое значение всегда усекается до максимальной длины символов, отображаемой в поле редактирования окна. Пользователь не может добавлять символы или заменять существующие символы, если строковое значение переменной среды длиннее символов.

Рекомендации по длине PATH

Система , хранящаяся в реестре Windows и в развернутом виде , не должна быть длиннеесимволов в Windows XP.

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

Другие вопросы по тегам