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

Dragokas

Very kind Developer
Команда форума
Супер-Модератор
Разработчик
Клуб переводчиков
Сообщения
6,013
Реакции
5,817
Баллы
648
choice записывает туда порядковый номер цифры, указанной вот в этом перечислении /C 1234567890.
Следовательно у нуля - 10-тый номер.

Нужно делать так:
CMD/BATCH:
echo.
echo 0. choice another version
echo.
if %n% LSS 10 (
  choice /C 1234567890 /M "Enter number: " /N
  call set ch=%%errorlevel%%
) else (
  set /p "ch=Enter number and press ENTER: "
)
if "%ch%"=="" goto dialog
if %n% LSS 10 if %ch%==10 goto single_setup
if %ch% GTR %n% goto dialog
if %ch% LSS 0 goto dialog
if %ch%==0 goto single_setup
Кстати, если всмотреться в код, я уже такой вариант писал ранее.

но если мы наберем 2.3
Нужно ставить защиту от ввода не-чисел. Позже напишу как.
Вот эту строку нужно вставить сразу следующей строкой после последней круглой скобки:
CMD/BATCH:
cmd /v /c echo !n!| findstr /R /C:"[^0-9]" >NUL && goto dialog
 
Последнее редактирование модератором:

alex_diablo

Активный пользователь
Сообщения
144
Реакции
9
Баллы
58
CMD/BATCH:
cmd /v /c echo !n!| findstr /R /C:"[^0-9]" >NUL && goto dialog
не помогло. если пишу 2.3 и подобное, скрипт продолжает работу как и прежде, только в переменные не передает значения, т.к. нечего передавать. если жму вместо цифр пробел и потом Enter - вылетает с ошибкой такого вида (в зависимости от количества пунктов в меню - цифры разные пишутся в ошибке):
Код:
Непредвиденное появление: 43.
еще вопрос: можем ли мы здесь:
CMD/BATCH:
choice /C 12 /m " Press key: " /n
увеличить отступ перед фразой Press key?
если ставить несколько пробелов, они не обрабатываются, т.е. строка выводится без пробелов сразу.. хотелось бы иметь возможность манипулировать этим, если возможно...
 
Последнее редактирование:

Dragokas

Very kind Developer
Команда форума
Супер-Модератор
Разработчик
Клуб переводчиков
Сообщения
6,013
Реакции
5,817
Баллы
648
alex_diablo, разумеется в ту строчку кода вместо переменной n нужно подставить ch. Это я в ком. строке по-быстрому так тестил.
еще вопрос: можем ли мы здесь:
Можно, если открыть батник каким-нибудь более продвинутым редактором, например, AkelPad, затем в месте, где нужен лидирующий пробел
зажать ALT+8, а затем пробел.
Тоже самое можно сделать и кодом, но будет чуть по-длиннее:
Код:
for /F "delims=#" %%a in ('"prompt #$H#& echo on &for %%A in (1) do rem"') do set "DEL=%%a"
choice /C 12 /m "%DEL% Press key: " /n
 

alex_diablo

Активный пользователь
Сообщения
144
Реакции
9
Баллы
58
CMD/BATCH:
echo %host% >> hosts_exist.txt
здесь мы значение переменной host записываем в файл.

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

Dragokas

Very kind Developer
Команда форума
Супер-Модератор
Разработчик
Клуб переводчиков
Сообщения
6,013
Реакции
5,817
Баллы
648
Не понял.
Если Вам нужно построчное считывание из этого файла, то это чаще всего реализуется циклом:
Код:
For /F "UseBackQ delims=" %%a in ("hosts_exist.txt") do echo Делаем что хотим с этой строкой: %%a
 

alex_diablo

Активный пользователь
Сообщения
144
Реакции
9
Баллы
58
возникла непредвиденная (неучтенная) проблема:

в куске кода:

CMD/BATCH:
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
все вроде хорошо, лишние символы из строки вырезаются, строка с нужным хостом в файл записывается... но вместе с полезными символами записываются и лишние пробелы...
и если на этапе пинга пробелы не учитываются и все ок, то на этапе работы psexec для установки софта в соответствии с хостами из файла hosts_exist.txt возникает проблема, psexec
лишние пробелы считает за символы и по логичной причине не может получить доступ к хостам из этого файла...
в результате чего дилемма... или переделывать полностью принцип обработки строк и выборки хостов и описаний... или как-то по другому обрезать лишние символы или удалять лишние пробелы..
в идеале - нужно просто из строки убирать \\ и все, что находится после хоста (пробелы и описание) и только сам хост помещать в файл hosts_exist.txt
в файле должны быть записаны только хосты. без пробелов, каждый с новой строки.
как это можно сделать?
проблема оказалась вобщем-то и не проблемой особо, решил так:

CMD/BATCH:
set host=%host:~2,15%
set host=%host: =%
 

alex_diablo

Активный пользователь
Сообщения
144
Реакции
9
Баллы
58
еще вопрос:

CMD/BATCH:
set /p version=" > Enter version of Unity: "

For /f "delims=" %%a in ('dir /b /s /a-d "%folder%\unity*.exe" ^| find "%version%"') do (
  set /a n+=1
  call set name[%%n%%]=%%~na
  call set path[%%n%%]=%%~fa
  call set fulpath[%%n%%]=%%~dpa
)
у нас в переменную %version% попадает то, что мы вводим изначально в поиске в ручную. т.е. если мы ищем версию 4.6.4p1 (UnitySetup_update-4.6.4p1.exe), не важно как ищем, вводя 4, 4.6, или полностью 4.6.4p1 - результаты поиска все равно отработают как положено, и скрипт сработает, программа установится... но переменная %version% в результате примет только то значение, которое мы ввели в ручную. а эта переменная в дальнейшем на этапе установки используется для задания конечно каталога установки (вида Unity_%version%) и если мы введем 4.6, а не 4.6.4p1 , то программа и установится в каталог Unity_4.6, что ни есть правильно. Тогда как в данном случае нам получить полный номер версии из имени файла и записать этот номер в переменную?
т.е. в данном примере - переменная, н-р: %version2% назовем ее так... должна принять значение: 4.6.4p1
и снова проблема не актуальна, т.к. проблемы то и не было, оказывается.... все решается лишь одной строкой...

CMD/BATCH:
for /f "tokens=2 delims=-" %%a in ("%unity_name%") do set version=%%a
 

alex_diablo

Активный пользователь
Сообщения
144
Реакции
9
Баллы
58
решил объединить разные куски в один код и где-то видать поломалось что-то, т.к. перестал работать поиск версии... (((

CMD/BATCH:
set msk=\\server1\Soft\Developers_Tools\Unity
set bj=\\server2\public\IT\Software\Unity
set sf=\\server3\Software\Unity3d

:: search share location
For /F "delims=" %%a in ('ipconfig ^| find /i "ipv4"') do call :FindIP "%%a"
if Defined a (set folder=%a% & goto psexec) ELSE (cls & echo. & echo. & echo.  Default Unity folder not found)
echo.
echo.
set /p folder="> Type folder with Unity: "


:FindIP
set "ip=%~1"
if "%ip:10.6=%" neq "%ip%"  set a=%msk%
if "%ip:10.5=%" neq "%ip%"  set a=%bj%
if "%ip:10.1=%" neq "%ip%"  set a=%sf%
exit /B

:psexec

:: default path for psexec:
set psexecfolder=%folder%

:: try if psexec exist in defoult folder. if no set path manually
:psexec1
cls
echo.
echo   .... Searching PsExec in default folder ...
echo.
echo.
For /f "delims=" %%a in ('dir /b /s /a-d "%psexecfolder%" ^| find /i "psexec.exe"') do call :psexec2 "%%a"
if defined a (set psexec=%a% & goto begin) else (cls & echo. & echo. & echo.  PsExec not found in default folder. ^
Try to search manually: )
echo.
echo.
set /p psexec=" Enter path for PsExec: "
set psexecfolder=%psexec%
goto psexec1

:psexec2
set "a=%~1"
exit /b

:begin

if exist %userprof%allhosts.txt (del %userprof%allhosts.txt)
if exist %userprof%installer.bat (del %userprof%installer.bat)
set installer=%userprof%installer.bat

:: where is host file
if exist %userprof%hosts.txt (del %userprof%hosts.txt)
set hostfile=%userprof%hosts.txt

set unity_path=0
set shortcut=%ALLUSERSPROFILE%\Microsoft\Windows\Start Menu\Programs\

cls
echo.
echo   Unity installer with PsExec:
echo   ============================
echo.
echo   1 Begin installation
echo   2 Exit
echo.
echo.
choice /C 12 /M "> Choose your action: " /N
if errorlevel 2 goto exit2
if errorlevel 1 goto single_setup

:single_setup

:: search unity installers file
set n=0
cls
echo.
set /p version=" > Enter version of Unity: "

For /f "delims=" %%a in ('dir /b /s /a-d "%folder%\unity*.exe" ^| find "%version%"') do (
  set /a n+=1
  call set name[%%n%%]=%%~na
  call set path[%%n%%]=%%~fa
  call set fulpath[%%n%%]=%%~dpa
)
cls
if  %n% GTR 1 goto dialog
if %n%==1 (set "ch=1" & goto EndDialog)
echo.
if %n%==0  echo   No files found! Try search again
echo.
echo.
echo   1 Search again
echo   2 Back to the main menu
echo.
echo.
choice /C 12 /M "> Choose your action: " /N
if errorlevel 2 goto :begin
if errorlevel 1 goto :single_setup
где-то пересекаются переменные??? не могу понять...
 
Последнее редактирование:

Dragokas

Very kind Developer
Команда форума
Супер-Модератор
Разработчик
Клуб переводчиков
Сообщения
6,013
Реакции
5,817
Баллы
648
1) После этой строки нет перехода goto
Код:
set /p folder="> Type folder with Unity: "
2) %userprof% - эта переменная где-нибудь задана?

3) exit2 такая метка есть?
CMD/BATCH:
choice /C 12 /M "> Choose your action: " /N
if errorlevel 2 goto :begin
if errorlevel 1 goto :single_setup
Зачем два раза писать одно и тоже, если можно написать goto метка

Почему не работает понять нельзя. Нужно расставить
Код:
echo Ключевая информация
pause
в ключевых моментах кода и смотреть где вывод не совпадает с ожидаемым.
 
Последнее редактирование модератором:

alex_diablo

Активный пользователь
Сообщения
144
Реакции
9
Баллы
58
1) После этой строки нет перехода goto
Код:
set /p folder="> Type folder with Unity: "
добавил goto psexec

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

CMD/BATCH:
For /F "delims=" %%a in ('ipconfig ^| find /i "ipv4"') do call :FindIP "%%a"
if Defined a (set folder=%a% & goto psexec) ELSE (cls & echo. & echo. & echo.  Default Unity folder not found)


2) %userprof% - эта переменная где-нибудь задана?

задана:

CMD/BATCH:
set userprof=%userprofile%\AppData\Local\Temp\
3) exit2 такая метка есть?

есть. выход в самом конце. проблема не в этом, т.к. до вставки кода:

:: search share location

и :: default path for psexec: все работало прекрасно...
т.е. если убираем эти 2 блока, все работает....

Код:
choice /C 12 /M "> Choose your action: " /N
if errorlevel 2 goto :begin
if errorlevel 1 goto :single_setup
Зачем два раза писать одно и тоже, если можно написать goto метка

поправил. убрал двоеточия.

Почему не работает понять нельзя. Нужно расставить
Код:
echo Ключевая информация
pause
в ключевых моментах кода и смотреть где вывод не совпадает с ожидаемым.
с паузой вроде делаю... отображение переменных делаю... пока через паузу вывожу - все ок. но на поиске версии по переменной %version%
не срабатывает поиск...
если закоментировать соответствующий блок в коде:

CMD/BATCH:
@ECHO OFF
SetLocal EnableExtensions
set userprof=%userprofile%\AppData\Local\Temp\
c:
cd %userprof%

set folder=\\server1\Soft\Developers_Tools\Unity

:: default folders with unity files

REM set msk=\\server1\Soft\Developers_Tools\Unity
REM set bj=\\server2\public\IT\Software\Unity
REM set sf=\\server3\Software\Unity3d

:: search share location

REM For /F "delims=" %%a in ('ipconfig ^| find /i "ipv4"') do call :FindIP "%%a"
REM if Defined a (set folder=%a% & goto psexec) ELSE (cls & echo. & echo. & echo.  Default Unity folder not found)
REM echo.
REM echo.
REM set /p folder="> Type folder with Unity: "

REM goto psexec

REM :FindIP
REM set "ip=%~1"
REM if "%ip:10.6=%" neq "%ip%"  set a=%msk%
REM if "%ip:10.5=%" neq "%ip%"  set a=%bj%
REM if "%ip:10.1=%" neq "%ip%"  set a=%sf%
REM exit /B

:psexec

:: default path for psexec:
set psexecfolder=%folder%

:: try if psexec exist in defoult folder. if no set path manually
:psexec1
cls
echo.
echo   .... Searching PsExec in default folder ...
echo.
echo.
For /f "delims=" %%a in ('dir /b /s /a-d "%psexecfolder%" ^| find /i "psexec.exe"') do call :psexec2 "%%a"
if defined a (set psexec=%a% & goto begin) else (cls & echo. & echo. & echo.  PsExec not found in default folder. ^
Try to search manually: )
echo.
echo.
set /p psexec=" Enter path for PsExec: "
set psexecfolder=%psexec%
goto psexec1

:psexec2
set "a=%~1"
exit /b

:begin

if exist %userprof%allhosts.txt (del %userprof%allhosts.txt)
if exist %userprof%installer.bat (del %userprof%installer.bat)
set installer=%userprof%installer.bat

:: where is host file
if exist %userprof%hosts.txt (del %userprof%hosts.txt)
set hostfile=%userprof%hosts.txt

set unity_path=0
set shortcut=%ALLUSERSPROFILE%\Microsoft\Windows\Start Menu\Programs\

cls
echo.
echo   Unity installer with PsExec:
echo   ============================
echo.
echo   1 Begin installation
echo   2 Exit
echo.
echo.
choice /C 12 /M "> Choose your action: " /N
if errorlevel 2 goto exit2
if errorlevel 1 goto single_setup

:single_setup

:: search unity installers file
set n=0
cls
echo.
set /p version=" > Enter version of Unity: "
echo %folder%
echo %version%
pause

For /f "delims=" %%a in ('dir /b /s /a-d "%folder%\unity*.exe" ^| find "%version%"') do (
  set /a n+=1
  call set name[%%n%%]=%%~na
  call set path[%%n%%]=%%~fa
  call set fulpath[%%n%%]=%%~dpa
)
cls
if  %n% GTR 1 goto dialog
if %n%==1 (set "ch=1" & goto EndDialog)
echo.
if %n%==0  echo   No files found! Try search again
echo.
echo.
echo   1 Search again
echo   2 Back to the main menu
echo.
echo.
choice /C 12 /M "> Choose your action: " /N
if errorlevel 2 goto begin
if errorlevel 1 goto single_setup

:: search results
:dialog
cls
echo.
For /L %%C in (1,1,%n%) do call echo   %%C.  %%name[%%C]%%
echo.
echo.
echo   0.  Choose another version
echo.
if %n% LSS 10 (
  choice /C 1234567890 /M "> Press number: " /N
  call set ch=%%errorlevel%%
  ) else (
  set /p "ch= Type number and press ENTER: "
)
cmd /v /c echo !ch!| findstr /R /C:"[^0-9]" >NUL && goto dialog
if "%ch%"=="" goto dialog
if %n% LSS 10 if %ch%==10 goto single_setup
if %ch% GTR %n% goto dialog
if %ch% LSS 0 goto dialog
if %ch%==0 goto single_setup

:EndDialog
cls
echo.
call set unity_path=%%path[%ch%]%%
call set unity_name=%%name[%ch%]%%
call set fulpath=%%fulpath[%ch%]%%
echo   Your choice is: %unity_name%
echo   In folder: %fulpath%
echo.
echo   1 Continue installation with this version
echo   2 Choose another version
echo   3 Back to list found
echo   4 Back to the main menu
echo   5 Exit
echo.
echo.
choice /C 12345 /M "> Choose your action: " /N
if errorlevel 5 goto exit2
if errorlevel 4 goto begin
if errorlevel 3 goto dialog
if errorlevel 2 goto single_setup
if errorlevel 1 goto setup2
и вручную задать переменную %folder%
то все прекрасно работает (как и раньше до добавления этого куска кода)
проблема где-то связанная с ним...

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

причем блок кода по поиску айпишника в данном случае работает...



up:

заменил поиск айпишника на другой ваш вариант:

CMD/BATCH:
set subnetCnt=4

set "subnet1=10.6"
set "subnet2=10.7"
set "subnet3=10.8"
set "subnet4=10.9"

set "office1=\\server1\Soft\Developers_Tools\Unity"
set "office2=\\server2\soft\"
set "office3=\\server3\soft\"
set "office4=\\server4\soft\"

For /F "delims=" %%a in ('ipconfig^| find /i "ipv4"') do (
  For /L %%C in (1,1,%subnetCnt%) do echo %%a|>NUL call find /i "%%subnet%%C%%" && set subnetNum=%%C
)
if defined subnetNum call set office=%%office%subnetNum%%%
set folder=%office%

if not defined subnetNum echo Subnet not found!
с этим вариантом вроде работает.
теперь хотелось бы таки понять, в чем кроется ошибка в том куске кода, ведь отдельно он работает?
 
Последнее редактирование:

Dragokas

Very kind Developer
Команда форума
Супер-Модератор
Разработчик
Клуб переводчиков
Сообщения
6,013
Реакции
5,817
Баллы
648
не срабатывает поиск...
Как это понимать?
Закомментированный блок кода задает что-нибудь переменной %a% и %folder% ?
У Вас, вероятно лишний пробел. Видите разницу?
Код:
REM if Defined a (set folder=%a% & goto psexec) ELSE (cls & echo. & echo. & echo.  Default Unity folder not found)
REM if Defined a (set folder=%a%& goto psexec) ELSE (cls & echo. & echo. & echo.  Default Unity folder not found)
 

alex_diablo

Активный пользователь
Сообщения
144
Реакции
9
Баллы
58
Как это понимать?
Закомментированный блок кода задает что-нибудь переменной %a% и %folder% ?
У Вас, вероятно лишний пробел. Видите разницу?
Код:
REM if Defined a (set folder=%a% & goto psexec) ELSE (cls & echo. & echo. & echo.  Default Unity folder not found)
REM if Defined a (set folder=%a%& goto psexec) ELSE (cls & echo. & echo. & echo.  Default Unity folder not found)
ну вы видите закоментированный кусок...
там задана переменная %folder% я дополнительно задал ее...
но дальше она все равно переназначается... так что врядли дело в ней.
убираю ее - результат не меняется.
а переменная %а%....
только если здесь...

CMD/BATCH:
REM if Defined a (set folder=%a% & goto psexec)

а разве (set folder=%a%& goto psexec)

тут не должно быть пробела между %а% и &?
 

alex_diablo

Активный пользователь
Сообщения
144
Реакции
9
Баллы
58
тема получила продолжение:

на файловой шаре много папок, в них лежат файлы вида: unitysetup-4.5.1.exe, unitysetup-4.5.4.exe, unitysetup-4.5.2.exe...
также в некоторых папках лежат файлы вида: UnitySetup64-5.3.4p5.exe, UnitySetup-Android-Support-for-Editor-5.3.4p5.exe, UnitySetup-iOS-Support-for-Editor-5.3.4p5.exe...

поиск ведется по номеру версии, например: 5.3.4р5

сейчас поиск файла и вывод списка выглядит так:

CMD/BATCH:
set /p version=" > Enter version of Unity: "

For /f "delims=" %%a in ('dir /b /s /a-d "%folder%\unitysetup*.exe" ^| find "%version%"') do (
  set /a n+=1
  call set name[%%n%%]=%%~na
  call set path[%%n%%]=%%~fa
  call set fulpath[%%n%%]=%%~dpa
)
cls
if  %n% GTR 1 goto dialog
if %n%==1 (set "ch=1" & goto EndDialog)
echo.
if %n%==0  echo   No files found! Try search again
echo.
echo.
echo   1 Search again
echo   2 Back to the main menu
echo   3 Exit
echo.
echo.
choice /C 123 /M "> Choose your action: " /N
if errorlevel 3 goto exit2
if errorlevel 2 goto begin
if errorlevel 1 goto single_setup

:: search results
:dialog
cls
echo.
For /L %%C in (1,1,%n%) do call echo   %%C.  %%name[%%C]%%
echo.
echo.
echo   0.  Choose another version
echo.
if %n% LSS 10 (
  choice /C 1234567890 /M "> Press number: " /N
  call set ch=%%errorlevel%%
  ) else (
  set /p "ch= Type number and press ENTER: "
)
cmd /v /c echo !ch!| findstr /R /C:"[^0-9]" >NUL && goto dialog
if "%ch%"=="" goto dialog
if %n% LSS 10 if %ch%==10 goto single_setup
if %ch% GTR %n% goto dialog
if %ch% LSS 0 goto dialog
if %ch%==0 goto single_setup

:EndDialog
cls
echo.
call set unity_path=%%path[%ch%]%%
call set unity_name=%%name[%ch%]%%
call set fulpath=%%fulpath[%ch%]%%
echo   Your choice is: %unity_name%
echo   In folder: %fulpath%
echo. 
echo   1 Continue installation with this version
echo   2 Choose another version
echo   3 Back to list found
echo   4 Back to the main menu
echo   5 Exit
echo.
echo.
choice /C 12345 /M "> Choose your action: " /N
if errorlevel 5 goto exit2
if errorlevel 4 goto begin
if errorlevel 3 goto dialog
if errorlevel 2 goto single_setup
if errorlevel 1 goto setup2

задача: в результатах поиска должны выводиться только файлы вида: UnitySetup64-5.3.4p5.exe (файлы: UnitySetup-Android-Support-for-Editor-5.3.4p5.exe, UnitySetup-iOS-Support-for-Editor-5.3.4p5.exe... выводиться в результатах не должны)

собственно задача - исключить из результата поиска файлы по маске: UnitySetup-Android-Support... , UnitySetup-iOS-Support ...
как это можно сделать?

можно конечно искать файлы по маске: unitysetup64*.exe, но тогда в результатах поиска будут выводиться только х64 версии, а нужно, чтобы поиск работал по всем версиям, т.к. заранее неизвестно, какой версии инсталятор.
 

Dragokas

Very kind Developer
Команда форума
Супер-Модератор
Разработчик
Клуб переводчиков
Сообщения
6,013
Реакции
5,817
Баллы
648
Здравствуйте, alex_diablo !

Это можно сделать, заменив 3-ю строку на:
CMD/BATCH:
For /f "delims=" %%a in ('dir /b /s /a-d "%folder%\unitysetup*.exe" ^| find "%version%" ^| find /i /v "UnitySetup-Android-Support" ^| find /i /v "UnitySetup-iOS-Support"') do (
 
Последнее редактирование модератором:

alex_diablo

Активный пользователь
Сообщения
144
Реакции
9
Баллы
58
блин... и правда... все так просто.. спасибо)
 
Сверху Снизу