PDA

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


элькхар
24-10-2012, 21:08
Написать программу, показывающую, какой файл выполнится, если набрать команду, переданную в параметрах.

Должны поддерживаться как команды с расширением, так и без (т.е. calc и calc.exe)

Пример запуска:
>which.cmd calc
C:\Windows\system32\calc.exe

//Желательно без использования сложных регулярных выражений.

Iska
24-10-2012, 21:36
@echo off
setlocal enableextensions enabledelayedexpansion

set sCommand=%~1

if defined sCommand (
if "%~x1" equ "" (
call :CheckExtension "%sCommand%" %pathext%
) else (
for %%i in ("%sCommand%") do if exist "%%~$PATH:i" echo "%%~$PATH:i"
)
) else (
echo Usage: %~nx0 ^<command^>
exit /b 1
)

endlocal
exit /b 0

:CheckExtension
setlocal enableextensions enabledelayedexpansion

:Repeat
set sExtension=%~2

if defined sExtension (
for %%i in ("%~1%sExtension%") do if exist "%%~$PATH:i" echo "%%~$PATH:i"
shift /2
goto :Repeat
)

endlocal
exit /b 0

элькхар
24-10-2012, 23:19
Огромное спасибо не расскажите как это работает?
1)enableextensions что делает этот параметр?
2)if "%~x1" equ "" что значит equ ? просмотрел справку по ифу не нашел
3)call :CheckExtension "%sCommand%" %pathext%зачем нужна данная строка? и что значит "%sCommand%" %pathext%

4)"%%~dp$PATH:i%%~i" зачем тут %%~i
5)echo Usage: %~nx0 ^<command^> Usage?? и %~nx0 ^<command^>
6)set sExtension=%~2~2 означает что берется все начиная с третьего символа, или я путаю?
7)if defined sExtensionесли она не пустая?

8)и по всему репиту немогу точно понять что он делает ~1,~2 и ~i ставят меня в тупик

Iska
25-10-2012, 02:41
1.
setlocal /?

2. «Если первый параметр командного файла имеет расширение, то …». Подробности:
call /?

что значит equ ? просмотрел справку по ифу не нашел »
Стало быть, у Вас Windows XP. Там в справке по «if /?» есть ошибка — написано «eql» вместо «equ». Означает — «equal», «равно». Можете почитать в chm-справке:
hh.exe mk:@MSITStore:C:\WINDOWS\Help\ntcmds.chm::/if.htm

3. «Вызвать новый контекст командного файла по метке «:CheckExtension», передав ему в качестве параметров переменные окружения «sCommand» и «pathext».

4. зачем тут %%~i »
Добавить к найденному пути («%%~dp$PATH:i%») имя самого файла.

Я тут просто «перебдел» c «dp». Можно упростить: «%%~dp$PATH:i%%~i» → «%%~$PATH:i». Я поправил код выше (http://forum.oszone.net/post-2011538.html#post2011538).

5. Можно так:
echo Использование: %~nx0 ^<команда^>
Это просто подсказка, вызываемая в случае, если командный файл был вызван без параметра.

6. Путаете. «Присвоить переменной окружения «sExtension» значение второго переданного на метку параметра».

7 и 8. если она не пустая? »
«Если переменная окружения «sExtension» существует».

Смотрите: мы вызываем процедуру (это, конечно, никакая не процедура, но так проще для разговора) «:CheckExtension» и передаём ей несколько параметров:
call :CheckExtension "%sCommand%" %pathext%
Что в неё приходит? Например, мы вызвали пакетный файл с параметром «notepad». Значит, в процедуру приходит первый параметр — имя файла «notepad» и содержимое переменной окружения «%pathext%», обычно это:
.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;
Следовательно, вторым параметром будет передан «.COM», третьим —«.EXE» и т.д. (дело в том, что точка с запятой — «;» — рассматривается командным процессором как разделитель, такой же как и пробел).

Рассмотрим ход исполнения:

:Repeat
set sExtension=%~2

if defined sExtension (
for %%i in ("%~1%sExtension%") do if exist "%%~$PATH:i" echo "%%~$PATH:i"
shift /2
goto :Repeat
)

по шагам.

На первом шаге переменная окружения «sExtension» принимает значение «.COM». Далее успешно проверяется, существует ли она. Затем, выполняется:
for %%i in ("%~1%sExtension%") do if exist "%%~$PATH:i" echo "%%~$PATH:i"
или, если подставить значения:
for %%i in ("notepad.COM") do if exist "%%~$PATH:i" echo "%%~$PATH:i"
что означает: проверить существование «notepad.COM» в путях, перечисленных в переменной окружения PATH и, если такой файл существует — вывести полный путь к нему. Поскольку файла «notepad.COM» в путях не будет найдено, ничего не будет выведено. Следующей командой — «shift /2» параметры процедуры:
"notepad" .COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;
будут «сдвинуты» таким образом:
"notepad" .EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;
Затем произойдёт переход к метке «:Repeat».

На втором шаге переменная окружения «sExtension» принимает значение «.EXE». Далее снова успешно проверяется, существует ли она. Затем, снова выполняется:
for %%i in ("%~1%sExtension%") do if exist "%%~$PATH:i" echo "%%~$PATH:i"
или, если подставить значения:
for %%i in ("notepad.EXE") do if exist "%%~$PATH:i" echo "%%~$PATH:i"
— проверить существование «notepad.EXE» в путях, перечисленных в переменной окружения PATH и, если такой файл существует — вывести полный путь к нему. Поскольку файл «notepad.EXE» будет найден в пути «C:\WINDOWS\system32\», будет выведено: «"C:\WINDOWS\system32\notepad.exe"». Затем снова командой — «shift /2» уже текущие параметры процедуры:
"notepad" .EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;
будут «сдвинуты» ещё «левее»:
"notepad" .BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;
Затем снова произойдёт переход к метке «:Repeat».

И так до тех пор, пока у нас после очередного исполнения «shift /2» параметры с:
"notepad" .WSH;
не примут вид:
"notepad"
Тогда на очередном шаге исполнения, после команды:
set sExtension=%~2
переменная окружения «sExtension» будет удалена (поскольку в этот момент второго параметра уже нет, не существует, остался только первый параметр «"notepad"»). Следовательно, условие в следующей команде «if defined sExtension …» окажется ложным и произойдёт выход из процедуры и возврат в контекст основного пакетного файла.


В принципе, можно предусмотреть условие, которое сразу будет прерывать последующий перебор расширений, как только будет найдено первое же совпадение.




© OSzone.net 2001-2012