Поиск файла и возможность выбора из нескольких найденных

alex_diablo

Постоянный участник
Сообщения
144
Реакции
9
Задача:
на файловой шаре, где много разного софта в куче разных вложенных подкаталогов есть прога (в данном случае Unity), у которой много разных версий (3.0.1, 3.0.2 ... 4.5.1, 4.5.2 и тд.). Все (или почти все) версии лежат каждая в отдельной папке (папки не обязательно пронумерованы по версии, вернее название папки может отличаться от шаблоны), установочные файлы именуются в виде: Unity_ver.4.6.1, setup_5.2.1 и т.д. т.е. каждая (почти каждая) версия пронумерована в соответствии с шаблоном вида *x.x.x.exe. нужно было сделать батник, в котором при вводе искомой версии установочного файла находился бы путь и подставлялся бы дальше в код скрипта (для дальнейшей установки на компы через psexec. после всех манипуляций с поиском, после нахождения полного пути до установочного файла, формируется автоматом другой батник и рассылается на требуемые компы.

сделал это так:

Код:
rem вводим версию
set /p version=" >>  Enter required version of Unity: "

rem ищем путь
where/r \\server\soft\Unity\ *%version%.exe >temp.txt

дальше переменную fulpath мы уже используем для подстановки в качестве пути для установки софта через psexec.

и все вроде бы хорошо, если например, вводишь 4.5.1 и файл с такими цифрами существует,
выводится полный путь с именем файла, который записываем во временный файл, а далее
записываем в переменную и уже используем где нужно:

Код:
set /p fullpath="" <temp.txt

Но на определенном этапе можно столкнуться с проблемой, что может оказаться два или более
одиннаковых результатов поиска (например: файл Unity_4.5.2.exe , который лежит в двух папках - x64 и х86, имя одинаковое, но разрядность разная, стало быть, разные файлы и лежат в разных местах). в этом случае в файл temp.txt скопируются все найденные пути, например:

CMD/BATCH:
\\server\soft\5.5.0\x86\unity_setup_5.5.0.exe
\\server\soft\5.5.0\x64\unity_setup_5.5.0.exe
\\server\soft\5.5.0\unity_setup_5.5.0.exe

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

частично сделал так:

Код:
 rem читаем файл, считаем количество строк и в отдельный файл записываем цифру, равную количеству строк:
find /c /v "" <"temp.txt" >string.txt

rem из временного файла с одним лишь символом (цифрой, обозначающей количество строк в файле temp.txt), записываем этот символ в переменную:
set /p string="" <string.txt

rem проверка на кол-во строк: если =1, то выполняется дальше условие по установке (через метку goto переходим к нужной части скрипта).
if %string%==1 goto install

rem если цифра больше 1, то выводится сообщение, вида:
echo    More then one path was founded:

rem и ниже выводим все строки с найденными путями:
echo.
type host2.txt

и вот на этом шаге нужно предложить юзеру выбрать нужный путь. но я не знаю, как сделать это
с использованием меню? например - у нас 3 файла в разных путях, нужно, чтобы юзер мог нажать
1, 2 или 3, в зависимости от того, какой путь ему интересен. желательно конечно, чтобы возле каждого пути стояла цифра кнопки, которую нужно нажать.

думается, делать это можно через choice и if errorlevel
но как правильно увязать это с результатами поиска я не знаю, на ум приходит только так:

Код:
set /p path=" >> type path manually: "

но это совсем не то, ибо вводить длиннющий путь вручную некрасиво и неудобно, теряется вообще смысл батника.
хотелось бы, чтобы в случае нахождения нескольких путей до файлов (например 3 файла) выводилось бы на экран что то типа этого:

CMD/BATCH:
"найдено n-файлов по заданной маске в следующих директориях:"

1 \\server\soft\5.5.0\x86\unity_setup_5.5.0.exe
2 \\server\soft\5.5.0\x64\unity_setup_5.5.0.exe
3 \\server\soft\5.5.0\unity_setup_5.5.0.exe

"выберите нужный файл"
т.е. по нажатию клавиш 1, 2 или 3 - у нас

прошу помощи в реализации задумки :) надеюсь, смысл задумки понятно объяснил...
зы. возможно, алгоритм поиска версии можно сделать по другому, лучше и проще и обойтись
без подсчета количества строк и записи все в отдельный файл...
буду рад любой помощи, включая оптимизацию кода)
 
Если цель - сделать как можно проще, то может номер версии вообще не вводить?

Попробуйте это:

CMD/BATCH:
@echo off
SetLocal EnableExtensions

set "Folder=\\server\soft\Unity"

set n=0

For /f "delims=" %%a in ('dir /b /s /a-d "%Folder%\setup*.exe" "%Folder%\Unity*.exe"') do (
  set /a n+=1
  call set name[%%n%%]=%%~na
  call set path[%%n%%]=%%~fa
  call echo %%n%%.  %%~na    -   %%~fa
)
echo.
if %n%==0 (echo No Files! & pause & goto :eof)

:dialog
set /p "ch=Enter number and press ENTER: "
if "%ch%"=="" goto dialog
if %ch% GTR %n% goto dialog

call set mypath=%%path[%ch%]%%
echo.
echo Your choice is: %mypath%
echo.
pause
 
скрипт ваш не запустился...
по поводу почему идет привязка к номеру версии: - потому что это фактически единственное, что делает конкретный файл уникальным, потому что файлы разных версий могут обзываться совершенно по-разному. где-то используется слово unity, где-то setup ... а цифровая версия почти во всех случаях уникальна. изначально от этого и плясали. на грабли наткнулись лишь тогда, когда случайно обнаружили (увидели и вспомнили), что по забывчивости или по глупости, где-то могут оказаться файлы разных разрядностей. опять же - зачем отображать все файлы (их может оказаться до сотни в итоге, если не больше) всех версий, если задача состоит в конкретизации. по сути пользователю известно точно, какую версию ему нужно установить. он не будет выбирать. для этого и нужно всего лишь указать конкретную версию, а просмотреть все существующие при необходимости можно и просто открыв шару. задача скрипта - максимально упростить раскатывание данного софта скажем, на 10 машин, делая это в несколько кликов.

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

Вложения

  • unity1.JPG
    unity1.JPG
    26.3 KB · Просмотры: 89
  • unity2.JPG
    unity2.JPG
    16.8 KB · Просмотры: 83
Это в смысле как не запустился, как запускали и что произошло?

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

Вложения

  • unity3.JPG
    unity3.JPG
    69.1 KB · Просмотры: 87
Последнее редактирование:
первый раз запускал с рабочего стола.
Может потому что я в скрипте свой путь оставил, потом отредактировал...

Если по номеру версии, тогда так:
CMD/BATCH:
@echo off
SetLocal EnableExtensions

set "Folder=\\server\soft\Unity"

set n=0

set /p "vers=Enter version: "

For /f "delims=" %%a in ('dir /b /s /a-d "%Folder%\setup*.exe" "%Folder%\Unity*.exe" ^| find "%vers%"') do (
  set /a n+=1
  call set name[%%n%%]=%%~na
  call set path[%%n%%]=%%~fa
  call echo %%n%%.  %%~na    -   %%~fa
)
echo.
if %n%==0 (echo No Files! & pause & goto :eof)

:dialog
set /p "ch=Enter number press ENTER: "
if "%ch%"=="" goto dialog
if %ch% GTR %n% goto dialog

call set mypath=%%path[%ch%]%%
echo.
echo Your choice is: %mypath%
echo.
pause
Можете и свою команду:
Код:
where/r \\server\soft\Unity\ *%version%.exe
вставить в скрипт, если ее работа Вас целиком удовлетворяла. Будет:
Код:
For /f "delims=" %%a in ('where /r \\server\soft\Unity\ *%vers%.exe') do (
 
вставить в скрипт, если ее работа Вас целиком удовлетворяла. Будет:

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

и нельзя ли таки обыграть вывод пути через choice, чтобы не нужно было набирать номер пункта, а просто нажимать кнопку, которая соответсвует номеру ?
 
Последнее редактирование:
Обратите внимание, что в XP нет встроенной утилиты choice.
По остальным замечаниям:

CMD/BATCH:
@echo off
SetLocal EnableExtensions

set "Folder=\\server\soft\Unity"

set n=0

set /p "vers=Enter version: "
echo.

For /f "delims=" %%a in ('dir /b /s /a-d "%Folder%\setup*.exe" "%Folder%\Unity*.exe" ^| find "%vers%"') do (
  set /a n+=1
  call set name[%%n%%]=%%~na
  call set path[%%n%%]=%%~fa
)
if %n%==0 (echo No Files! & pause & goto :eof)
if %n%==1 (set "ch=1" & goto EndDialog)
:dialog
For /L %%C in (1,1,%n%) do call echo %%C.  %%name[%%C]%%    -   %%path[%%C]%%
echo.
if %n% LSS 10 (
  choice /C 123456789 /M "Enter number: " /N
  call set ch=%%errorlevel%%
) else (
  set /p "ch=Enter number press ENTER: "
)
if "%ch%"=="" goto dialog
if %ch% GTR %n% goto dialog
if %ch% LSS 0 goto dialog
:EndDialog

call set mypath=%%path[%ch%]%%
echo.
echo Your choice is: %mypath%
echo.
pause
 
большое спасибо! реализовано все, что нужно! все работает отлично!
в продолжении темы... есть похожая задача, вернее, она предшествует скрипту выше:

Итак: прежде, чем выполнить скрипт по поиску нужной версии программы, нужно определиться,
на какой комп (ы) будем ее устанавливать.
Для этого через net view выполняем поиск всех хостов. У нас на всех компах в сети присутствует описание компа (имя и фамилия пользователя), поэтому поиск можно осуществлять по фио.
все хосты вида подразделение-первая буква имени и фамилия:
msk-aivanov
msk-bpetrov

все имена хостов - не длиннее 15 символов, т.е. если по шаблону не получается уместить полностью фио и уложиться в 15 символов, просто обрезаем конец фамилии, либо что-то подобное: msk-dpervoproh (в описании напротив хоста будет: dmitry pervoprohodcev)
итак, для поиска хоста мы можем забить либо часть фио, которая будет частью хоста, либо ввести полностью: dmitry pervoprohodcev
далее скрипт должен в файле найти нужный хост и записать его в переменную (для дальнейшей работы с ним при использовании скрипта для установки выше)
проблема в том, что у некоторых юзеров может быть 1, 2 или даже 3 компа (ноута), хосты у них будут немного отличаться (буква, цифра и тд.), а описание будет одинаковое (фио)
поэтому нужна возможность выбора в случае чего.
ниже мой кривой :) код:

CMD/BATCH:
@echo off
rem ищем все хосты и записываем в файл.
net.exe view > host1.txt
setlocal
:1
cls
echo.
echo.
set /p name=" >> Enter the name of user: "
rem в списке всех найденных хостов находим нужный и записываем в другой файл
findstr /i /c:"%name%" host1.txt > host2.txt
rem тут проверяем, найден ли какой-либо хост по шаблону поиска
if %errorlevel%==1 goto 2
rem если  хост найден не один, считаем количество найденных хостов и в еще один файл записываем цифру, равную количеству строк
find /c /v "" <"host2.txt" >string.txt
set /p string="" <string.txt
rem если строка 1
rem если хост один, идем на шаг 3
if %string%==1 goto 3
cls
echo.
echo    More then one HOST was founded:
echo.
echo.
rem выводим список всех найденных (похожих хостов)
type host2.txt
echo.
echo.
echo   1 Type HOST manually
echo   2 Back to the main menu
echo   3 Exit
echo.
echo.
choice /C:123 /m "choose your action:"
if errorlevel 3 goto exit
if errorlevel 2 goto 1
if errorlevel 1 goto a
:a
cls
echo.
echo.
type host2.txt
echo.
echo.
rem смотрим список найденных хостов выше и вводим нужный
set /p host=" >> type hostname manually: "
rem на всякий случай, проверяем доступность хоста (вдруг внезапно выключили комп)))
ping %host% | find /i "ttl"
if %errorlevel%==1 goto 2
rem если хост найден, записываем его (тот самый хост, который нужен. в дальнейшем, psexec будет подставлять этот файл для установки софта на комп, который указан в этом файле)
echo %host% > hosts_exist.txt
goto exit
:2
echo host for %name% not found. Try to type the name again.
echo.
endlocal
choice /C:12 /m "> choose your action:"
if errorlevel 2 goto exit
if errorlevel 1 goto 1
:3
cls
set /p host="" <host2.txt
rem обрезаем все лишнее (убираем \\ и описание компа. оставляем только 15 символов)
set host=%host:~2,15%
ping %host% | find /i "ttl"
if %errorlevel%==1 goto 2
echo %host% > hosts_exist.txt
echo.
echo.
echo   host %host% is ready.
echo.
choice /C:12 /m "> choose your action:"
echo.
endlocal
if errorlevel 2 goto exit
if errorlevel 1 goto 1
:exit
del host1.txt
del hosts_exist.txt
del host2.txt
del string.txt

только не кидайте сразу шапками пожалуйста)) согласен, скрипт УГ и сделан на коленке) увы, пока еще только начинаю этим заниматься и с циклами пока что очень плохо получается (но начальство ставит задачи, которые нужно каким-то образом выполнять).
поэтому буду признателен за помощь в оптимизации кода, возможно на примере предыдущего скрипта, как я понимаю, ситуация здесь примерно похожа? только ищем мы не пути файлов, а строки с хостами...
 
Просто - это не означает, что плохо.

CMD/BATCH:
@echo off
rem ищем все хосты и записываем в файл.
net.exe view > host1.txt
echo.
:1
cls
:1a
echo.
set /p name=" >> Enter the NAME of user: "
rem в списке всех найденных хостов находим нужный и записываем в другой файл
set n=0
for /F "delims=" %%a in ('findstr /i /c:"%name%" host1.txt') do (
  set /a n+=1
  call set host[%%n%%]=%%a
)
rem тут проверяем, найден ли какой-либо хост по шаблону поиска
rem ни одного хоста не найдено
if %n%==0 (echo No names! & goto 1a)
rem если хост один, идем на шаг 3
if %n%==1 goto 3
rem если хостов найдено несколько, выводим их все и предлагаем указать цифру соответствующую этому хосту
echo.
echo    More then one HOST was founded:
:ch1
cls
:ch1a
echo.
rem выводим список всех найденных (похожих хостов)
For /L %%C in (1,1,%n%) do call echo   %%C.  %%host[%%C]%%
echo.
echo   0 - Back to the main menu
echo.
if %n% GTR 9 (
  set /p "ch=Type HOST number and press ENTER: "
) else (
  choice /C 1234567890 /m "Type HOST number: " /N
  call set ch=%%errorlevel%%
)
if %n% LSS 10 if %ch%==10 goto 1
if %ch% GTR %n% goto ch1
if %ch% LSS 0 goto ch1

call set host=%%host[%ch%]%%
echo Your choice: %host%

:3
rem обрезаем все лишнее (убираем \\ и описание компа. оставляем только 15 символов)
set host=%host:~2,15%

:: Проверяем доступность хоста
ping %host% | find /i "ttl" || (
  echo host for %name% not found.
  rem Хост был только 1, предлагаем провести новый поиск по имени
  if %n%==1 goto 1a
  rem Хостов было найдено больше 1, предлагаем ввести новый номер похожего хоста.
  goto ch1a
)

rem если хост найден, записываем его (тот самый хост, который нужен. в дальнейшем, psexec будет подставлять этот файл для установки софта на комп, который указан в этом файле)

echo %host% > hosts_exist.txt
echo.
echo.
echo   host %host% is ready.
echo.
echo.
echo 1 - Find new name
echo 2 - Exit
echo.
choice /C:12 /m "> choose your action: "
if %errorlevel%==1 goto 1
:exit
del host1.txt
del hosts_exist.txt
 
Просто - это не означает, что плохо.

CMD/BATCH:
@echo off
rem ищем все хосты и записываем в файл.
net.exe view > host1.txt
echo.
:1
cls
:1a
echo.
set /p name=" >> Enter the NAME of user: "
rem в списке всех найденных хостов находим нужный и записываем в другой файл
set n=0
for /F "delims=" %%a in ('findstr /i /c:"%name%" host1.txt') do (
  set /a n+=1
  call set host[%%n%%]=%%a
)
rem тут проверяем, найден ли какой-либо хост по шаблону поиска
rem ни одного хоста не найдено
if %n%==0 (echo No names! & goto 1a)
rem если хост один, идем на шаг 3
if %n%==1 goto 3
rem если хостов найдено несколько, выводим их все и предлагаем указать цифру соответствующую этому хосту
echo.
echo    More then one HOST was founded:
:ch1
cls
:ch1a
echo.
rem выводим список всех найденных (похожих хостов)
For /L %%C in (1,1,%n%) do call echo   %%C.  %%host[%%C]%%
echo.
echo   0 - Back to the main menu
echo.
if %n% GTR 9 (
  set /p "ch=Type HOST number and press ENTER: "
) else (
  choice /C 1234567890 /m "Type HOST number: " /N
  call set ch=%%errorlevel%%
)
if %n% LSS 10 if %ch%==10 goto 1
if %ch% GTR %n% goto ch1
if %ch% LSS 0 goto ch1

call set host=%%host[%ch%]%%
echo Your choice: %host%

:3
rem обрезаем все лишнее (убираем \\ и описание компа. оставляем только 15 символов)
set host=%host:~2,15%

:: Проверяем доступность хоста
ping %host% | find /i "ttl" || (
  echo host for %name% not found.
  rem Хост был только 1, предлагаем провести новый поиск по имени
  if %n%==1 goto 1a
  rem Хостов было найдено больше 1, предлагаем ввести новый номер похожего хоста.
  goto ch1a
)

rem если хост найден, записываем его (тот самый хост, который нужен. в дальнейшем, psexec будет подставлять этот файл для установки софта на комп, который указан в этом файле)

echo %host% > hosts_exist.txt
echo.
echo.
echo   host %host% is ready.
echo.
echo.
echo 1 - Find new name
echo 2 - Exit
echo.
choice /C:12 /m "> choose your action: "
if %errorlevel%==1 goto 1
:exit
del host1.txt
del hosts_exist.txt

а одинаковые имена переменных в этом и предыдущем коде в одном скрипте не будут пересекаться и мешать работе друг друга?

зы. почему то не находит по имени и фамилии. т.е. пишешь: ivan petrov - пишет хост нот фаунд. но если вводишь только ivan или petrov, то выводит все найденные по маске хосты... где косяк?
 
Последнее редактирование:
в команде findstr. Я скопипастил, не обратив внимание.
Перепишите участок кода с использованием команды find:
Код:
for /F "delims=" %%a in ('2^>NUL find /i "%name%" ^< host1.txt') do (
Если все равно не сработает, пришлите файл host1.txt (именно в виде файла!) (можно только с той строкой, которую не находит).

а одинаковые имена переменных в этом и предыдущем коде в одном скрипте не будут пересекаться и мешать работе друг друга?
Пересечение только на переменной n.
Пока код выполняется последовательно, без перекрестных вызовов (а здесь иначе и не будет), все будет хорошо.
Я даже SetLocal из этого кода убрал, зная что возможно, захотите зациклить оба кода по кругу.
Иначе это могло привести к переполнению стека и вылету.
На счет того, что переменные не очищаются, здесь маркером служит та самая переменная n.
Как видите, в обоих случаях, ей сперва присваивается 0.
Условные проверки с другими переменными не используются.
 
в команде findstr. Я скопипастил, не обратив внимание.
Перепишите участок кода с использованием команды find:
Код:
for /F "delims=" %%a in ('2^>NUL find /i "%name%" ^< host1.txt') do (
Если все равно не сработает, пришлите файл host1.txt (именно в виде файла!) (можно только с той строкой, которую не находит).


Пересечение только на переменной n.
Пока код выполняется последовательно, без перекрестных вызовов (а здесь иначе и не будет), все будет хорошо.
Я даже SetLocal из этого кода убрал, зная что возможно, захотите зациклить оба кода по кругу.
Иначе это могло привести к переполнению стека и вылету.
На счет того, что переменные не очищаются, здесь маркером служит та самая переменная n.
Как видите, в обоих случаях, ей сперва присваивается 0.
Условные проверки с другими переменными не используются.

сделал так:

CMD/BATCH:
for /F "delims=" %%a in ('find /i host1.txt "%name%"') do (

поиск заработал, строка находится, но результат выглядит так:

Код:
  1.  ---------- HOST1.TXT
  2.  \\MSK-AAIVANOV           Alexander Ivanov
  3.  \\MSK-APETROV          Alexander Petrov
  4.  \\MSK-ASIDOROV         Alexander Sidorov
 
  0 - Back to the main menu

Type HOST number:

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

up:

если делаю так:

CMD/BATCH:
for /F "delims=" %%a in ('2^>NUL find /i "%name%" ^< host1.txt') do (

поиск срабатывает, и выглядит все так:

Код:
  1.  \\MSK-AAIVANOV           Alexander Ivanov
  2.  \\MSK-APETROV          Alexander Petrov
  3.  \\MSK-ASIDOROV         Alexander Sidorov

но только если поиск делать лишь по имени или только по фамилии.
если я ввожу Alexander Ivanov, то результат команды:

Код:
>> Enter the NAME of user: Alexander Ivanov
host for Alexander Ivanov not found.
 
Последнее редактирование:
......
Если все равно не сработает, пришлите файл host1.txt (именно в виде файла!) (можно только с той строкой, которую не находит).
Только не копируйте конкретную строку в другой файл -> удалите все лишнее из исходного и сохраните.
Хочется взглянуть что там в качестве разделителя у команды net view.
Сейчас нет доступа ни к каким сеткам, чтобы на чем то живом проверить.
Ну а в целом должно вот так заработать:

CMD/BATCH:
for /F "skip=1 delims=" %%a in ('2^>NUL find /i host1.txt "%name%"') do (
 
файл во вложении
если делаю так

CMD/BATCH:
for /F "skip=1 delims=" %%a in ('2^>NUL find /i host1.txt "%name%"') do (

то результат такой:

Код:
 1.  ---------- HOST1.TXT
  2.  \\MSK-AAIVANOV           Alexander Ivanov
  3.  \\MSK-APETROV          Alexander Petrov
  4.  \\MSK-ASIDOROV         Alexander Sidorov
  0 - Back to the main menu

Type HOST number:

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

Вложения

  • host1.txt
    353 байт · Просмотры: 4
Последнее редактирование модератором:
У меня с этим файлом все отрабатывает нормально (имя+фамилия). Не могу установить причину проблемы.
Какая версия ОС?

Чтобы убрать шапку, нужно пропустить больше строк.
Напишите:
CMD/BATCH:
for /F "skip=2 delims=" %%a in ('2^>NUL find /i host1.txt "%name%"') do (
 
Какая версия ОС?

win 7 pro x64 rus
вот именно так:
CMD/BATCH:
for /F "skip=2 delims=" %%a in ('2^>NUL find /i host1.txt "%name%"') do (

у меня по имени и фамилии (alexander sidorov) не находит.
только по alexander или только по sidorov.
не пойму, где собака порылась...

т.е. если не использовать skip, то все ищется, но в пункте меню 1 выводится имя файла. если ставлю skip=1, все то же самое, но если ставлю skip=2 - перестает находить.
 
Последнее редактирование модератором:
Ага. Нашел. Ошибка совсем в другом месте.
Когда находит только 1 совпадение, переменной host ничего не присваивается.
Вот исправленный код:

CMD/BATCH:
@echo off
rem ищем все хосты и записываем в файл.
net.exe view > host1.txt
echo.
:1
cls
:1a
echo.
set /p name=" >> Enter the NAME of user: "
rem в списке всех найденных хостов находим нужный и записываем в другой файл
set n=0
for /F "skip=2 delims=" %%a in ('2^>NUL find /i host1.txt "%name%"') do (
  set /a n+=1
  call set host[%%n%%]=%%a
  set host=%%a
)
rem тут проверяем, найден ли какой-либо хост по шаблону поиска
rem ни одного хоста не найдено
if %n%==0 (echo No names! & goto 1a)
rem если хост один, идем на шаг 3
if %n%==1 goto 3
rem если хостов найдено несколько, выводим их все и предлагаем указать цифру соответствующую этому хосту
echo.
echo    More then one HOST was founded:
:ch1
cls
:ch1a
echo.
rem выводим список всех найденных (похожих хостов)
For /L %%C in (1,1,%n%) do call echo   %%C.  %%host[%%C]%%
echo.
echo   0 - Back to the main menu
echo.
if %n% GTR 9 (
  set /p "ch=Type HOST number and press ENTER: "
) else (
  choice /C 1234567890 /m "Type HOST number: " /N
  call set ch=%%errorlevel%%
)
if %n% LSS 10 if %ch%==10 goto 1
if %ch% GTR %n% goto ch1
if %ch% LSS 0 goto ch1

call set host=%%host[%ch%]%%

:3
echo Your choice: %host%
rem обрезаем все лишнее (убираем \\ и описание компа. оставляем только 15 символов)
set host=%host:~2,15%

:: Проверяем доступность хоста
ping %host% | find /i "ttl" || (
  echo host for %name% not found.
rem Хост был только 1, предлагаем провести новый поиск по имени
  if %n%==1 goto 1a
rem Хостов было найдено больше 1, предлагаем ввести новый номер похожего хоста.
  goto ch1a
)

rem если хост найден, записываем его (тот самый хост, который нужен. в дальнейшем, psexec будет подставлять этот файл для установки софта на комп, который указан в этом файле)

echo %host% > hosts_exist.txt
echo.
echo.
echo   host %host% is ready.
echo.
echo.
echo 1 - Find new name
echo 2 - Exit
echo.
choice /C:12 /m "> choose your action: "
if %errorlevel%==1 goto 1
:exit
del host1.txt
del hosts_exist.txt
 
добавил в код дополнительный пункт меню - 0:

CMD/BATCH:
For /L %%C in (1,1,%n%) do call echo %%C.  %%name[%%C]%%
echo.
echo 0. choice another version
echo.
if %n% LSS 10 (
  choice /C 123456789 /M "Enter number: " /N
  call set ch=%%errorlevel%%
) else (
  set /p "ch=Enter number press ENTER: "
)
if "%ch%"=="" goto dialog
if %ch% GTR %n% goto dialog
if %ch% LSS 0 goto dialog
if %ch%==0 goto single_setup

т.е. если после того, как на экран выводится список меню, ниже есть 0, т.е. по нажатию возвращаемся к началу. но не работает, если в меню меньше 10 пунктов. если больше 10, то при ручном вводе цифры 0 и по нажатию enter все срабатывает. где косяк?

и еще один баг обнаружил, когда в меню больше 10 пунктов:

если ввести например 23 и в меню есть этот пункт, все ок. если мы нажимаем например 23. , то скрипт не срабатывает, ок. но если мы наберем 2.3 , скрипт делает так, как должен при положительном результате срабатывать, но при этом ничего в пути не показывает... вроде бы логично, что не нужно так нажимать, но если нажать, скрипт продолжает работу не выполнив предыдущего пункта... неприятно... не знаю как пофиксить...
 
Последнее редактирование:
Назад
Сверху Снизу