Войти

Показать полную графическую версию : Как взять в цикл FOR имена изнутри самого исполняемого CMD


alexys2004
11-04-2025, 07:07
Здравия всем!
Уважаемые знатоки, требуется ваша помощь!
Есть стандартный цикл, который берёт из внешнего файла имена и записывает их в другой файл!
Пока этих файлов была пара, было терпимо, а теперь россыпь из десятка файлов начинает раздражать! :(
Возможно ли сделать так, чтобы цикл брал имена из списка внутри самого исполняемого CMD ?
Например, цикл обращается к некоему списку имён, который прячется в конце файла после EXIT и дальше записывает их во внешний файл..


SET NAME=:список
FOR /F "usebackq tokens=* delims=" %%i IN ("%NAME%") DO (ECHO %%i>> файл.txt)
EXIT

:список откуда брать имена
ИМЯ1
ИМЯ2
ИМЯ3


Крайне благодарен, если есть решение!

NickM
11-04-2025, 07:33
Не совсем список, но, работает:
@echo off
SetLocal EnableExtensions EnableDelayedExpansion

SET "len=5"
FOR /l %%i IN (1,1,%len%) DO (
call :NAME%%i
ECHO. !name! >> файл.txt
)
goto :EOF
exit

:NAME1
set "name=ИМЯ1"
goto :EOF

:NAME2
set "name=ИМЯ2"
goto :EOF

:NAME3
set "name=ИМЯ3"
goto :EOF

:NAME4
set "name=ИМЯ4"
goto :EOF

:NAME5
set "name=ИМЯ5"
goto :EOF

А, вообще, вариантов много можно придумать, например, с тем же временным файлом, в который список помещать, а после его читать и прочее.

alexys2004
11-04-2025, 07:49
Такой вариант у меня уже был, очень трудно искать и редактировать список имён!

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

Нужен, если есть, именно вариант с обращением к голому списку внутри самого CMD ?

NickM
11-04-2025, 08:48
Что касается "временного файла" - тоже думал, но в крайнем случае.. проще, наверное, всю эту россыпь в архив собрать. »
Никакой россыпи, например:
@echo off
SET "file_with_name=%temp%\file_with_name.txt"
more +9 "%~0">"%file_with_name%"

FOR /F "usebackq tokens=* delims=" %%i IN ("%file_with_name%") DO (ECHO %%i)
del /f /q "%file_with_name%"
EXIT

:список имён
ИМЯ1
ИМЯ2
ИМЯ33
ИМЯ4
ИМЯ5

alexys2004
11-04-2025, 10:28
Не очень понял - в какой момент имена из раздела ":список имён" выносятся во временный файл?

и что делает операция:
more +9 "%~0">"%file_with_name%"

И ещё, я забыл сделать акцент в первом посте:
таких списков будет НЕ один, т.к. внешних файлов уже почти десяток - вот от них я хочу избавиться и засунуть все списки в один исполняемый файл, но каждый отдельно, чтобы обрабатывался по мере необходимости!
Собрать всё в один список - не вариант! надо, чтобы создавался в нужный момент отдельный файл с отдельным списком, взятым из конкретной области в исполняемом файле!


SET NAME=:список 1
FOR /F "usebackq tokens=* delims=" %%i IN ("%NAME%") DO (ECHO %%i>> файл.txt)
SET NAME=:список 2
FOR /F "usebackq tokens=* delims=" %%i IN ("%NAME%") DO (ECHO %%i>> файл.txt)
EXIT

:список 1
ИМЯ11
ИМЯ12
ИМЯ13

:список 2
ИМЯ21
ИМЯ22
ИМЯ23

NickM
11-04-2025, 10:40
И ещё, я забыл сделать акцент в первом посте:
таких списков будет НЕ один »
Это акцентище!

Не очень понял - в какой момент имена из раздела ":список имён" выносятся во временный файл? »
и что делает операция:
more +9 "%~0">"%file_with_name%" »
Именно это и делает - наполняет временный файл списком;

Собрать всё в один список - не вариант! надо, чтобы создавался в нужный момент отдельный файл с отдельным списком, взятым из конкретной области в исполняемом файле! »
Можно наверное и здесь что-нибудь придумать.

Sham
11-04-2025, 12:52
если список брать из внутренней переменной, то переносы нужно экранировать, оставляя пробелы между именами @echo off
goto set_list1
:do
for %%i in (%LIST%) do echo "%%i"
pause
exit

:set_list1
set LIST=ИМЯ11^
ИМЯ12^
ИМЯ13
goto do
иначе нужно читать сам этот скрипт извне и искать в нём текст этого списка либо построчным поиском, либо регулярным выражением. Тут уже надо определяться с языком скрипта или утилитами типа grep, которых нет в системе.

DJ Mogarych
11-04-2025, 12:57
Powershell, запрос номера списка и вывод в файл.

$list1 = ("
ИМЯ11
ИМЯ12
ИМЯ13
") -split "`n" -match "\w"

$list2 = ("
ИМЯ21
ИМЯ22
ИМЯ23
") -split "`n" -match "\w"

$list3 = ("
ИМЯ31
ИМЯ32
ИМЯ33
") -split "`n" -match "\w"

$l = read-host "Номер списка для вывода в файл"
switch ($l) {
1 {$selectedList = $list1}
2 {$selectedList = $list2}
3 {$selectedList = $list3}
}
$selectedList |out-file "c:\temp\file.txt" -Encoding default

NickM
11-04-2025, 13:36
Можно наверное и здесь что-нибудь придумать. »
Изврат какой-то получился, но вроде работает как того требуется - списки в файле, обрамлены концом и началом:
@echo off
SetLocal EnableExtensions EnableDelayedExpansion
set /p "spisok=Ведите № списка:"

for /f "tokens=* delims=" %%i in ('more "%~0" ^| findstr /n "begin_%spisok%"') do (
set "b=%%i"
set "b=!b:::begin_%spisok%=!"
)

for /f "tokens=* delims=" %%i in ('more +%b% "%~0"') do (
if "%%i" NEQ ":end_%spisok%" (echo. %%i)
if "%%i" EQU ":end_%spisok%" goto :EOF
)

:begin_1
ИМЯ11
ИМЯ12
ИМЯ13
:end_1

:begin_2
ИМЯ21
ИМЯ22
ИМЯ23
ИМЯ24
:end_2

:begin_3
ИМЯ31
ИМЯ32
ИМЯ33
:end_3

:begin_4
ИМЯ41
ИМЯ42
:end_4

:begin_5
ИМЯ51
ИМЯ52
ИМЯ53
ИМЯ54
ИМЯ55
:end_5

megaloman
11-04-2025, 16:59
@Echo Off &Cls
Set "BoxOut=Z:\Box_Out"

Set "@S1=File1.txt"
Set "@S2=File2.txt"
Set "@S3=File3.txt"
Set "@S12345=File777.txt"

Pushd "%BoxOut%"||(Echo Folder "%BoxOut%" not found &Pause &Exit /B 2)
For /f "usebackq tokens=1* delims==" %%i IN (`Set "@S"`) Do >nul 2>&1 Del "%BoxOut%\%%j"
For /f "usebackq tokens=1* delims=:" %%i IN (`FindStr /R /N /C:"^:@S" "%~dpnx0"`) Do Call :Out %%i %%j
Pause
Exit /B

:Out
Call Set "OutFile=%%%2%%"
For /f "usebackq delims=" %%s IN (`More +%1 "%~dpnx0"`) Do (
Echo "%%s"|>nul Find ":@S"&&Exit /B
>>"%BoxOut%\%OutFile%" Echo %%s
)
Exit /B

:@S1
C:\Program Files\1 skjhdk kslhjdljsl sl;djl;jlsjd.txt
C:\Program Files\Advanced IP Scanner\2 sslm jds;ll; dalj;al lajl;akjsl;ka.png
C:\Program Files (x86)\3 aklljalkjs akjslkajlasjl akljlakjljs.dbf

:@S2
C:\Program Files\4 adSA SDASD DADADD.xls
C:\Program Files (x86)\5 aSDFDSA CSAS SAASAS.doc

:@S12345
8 adSA SDASD DADADD.xls
9 aSDFDSA CSAS SAASAS.doc

:@S3
C:\Program Files (x86)\6 adSA SDASD DADADD.xls
C:\Program Files\7 aSDFDSA CSAS SAASAS.doc

1. Списки должны быть последними в батнике.
2. Перед списками обязательно должен быть Exit
3. Список должен именоваться @Sxxxx и начинаться :@Sxxxx
4. Для каждого списка должно указываться имя выходного файла. Для разных списков выходной файл может совпадать.

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

alexys2004
12-04-2025, 06:28
DJ Mogarych, Powershell, запрос номера списка и вывод в файл. »

немного не то! да и Powershell я совсем плохо понимаю.. :sorry:

megaloman,
это прям КРУТО! :up
только я не совсем ещё понял, как это работает..
надо разобраться, как записывать не все файлы сразу, а нужный в конкретный момент..
можно я попробую разобраться и ещё раз Вас спрошу, если понадобится?

megaloman,
если я правильно понял, цикл

For /f "usebackq tokens=1* delims=:" %%i IN (`FindStr /R /N /C:"^:@S" "%~dpnx0"`) Do Call :Out %%i %%j
находит все @S, вызывает функцию, которая записывает найденные имена в файлы, которые созданы строкой выше?

а если в конкретный момент времени мне надо записать имена из конкретного списка в конкретный файл, то мне достаточно только самой функции :Out без перебора всех списков в цикле? только нужно подставить конкретные имена вместо переменных в этот цикл, опустив предыдущие 2 цикла перебора файлов и списков?


Call Set "OutFile=%%%2%%"
For /f "usebackq delims=" %%s IN (`More +%1 "%~dpnx0"`) Do (
Echo "%%s"|>nul Find ":@S"&&Exit /B
>>"%BoxOut%\%OutFile%" Echo %%s

alexys2004
12-04-2025, 07:04
megaloman,

сократил вот так:


@Echo Off &Cls
Set "BoxOut=D:\Box_Out"

For /f "usebackq tokens=1* delims=:" %%i IN (`FindStr /R /N /C:"^:@S1" "%~dpnx0"`) Do Call :Out %%i %%j
Pause
Exit /B

:Out
For /f "usebackq delims=" %%s IN (`More +%1 "%~dpnx0"`) Do (
Echo "%%s"|>nul Find ":@S"&&Exit /B
>>"%BoxOut%\list1.txt" Echo %%s
)
Exit /B

:@S1
C:\Program Files\1 skjhdk kslhjdljsl sl;djl;jlsjd.txt
C:\Program Files\Advanced IP Scanner\2 sslm jds;ll; dalj;al lajl;akjsl;ka.png
C:\Program Files (x86)\3 aklljalkjs akjslkajlasjl akljlakjljs.dbf

:@S2
C:\Program Files\4 adSA SDASD DADADD.xls
C:\Program Files (x86)\5 aSDFDSA CSAS SAASAS.doc


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

Sham
12-04-2025, 10:47
FindStr*/R*/N*/C:"^:@S1 »
насколько понял, ищется в этом файле скрипта строка содержащая ":@S" (заголовок списка), и в функцию передаётся номер строки и сама строка целиком (вывод FindStr, разделённый по delim). Дальше more позволяет начать чтение файла с этого номера строки. Чтобы конкретизировать список нужно передать в FindStr более конкретный заголовок списка, а не :@S.

megaloman
12-04-2025, 11:08
@Echo Off &Cls
If Not "%~1"=="" If Not "%~2"=="" GoTo :Begin
Echo The script arguments must contain the name of the list and the name of the output file!
Echo Script terminated! &Pause &Exit /B 2
:Begin
If Not Exist "%~dp2" (Echo Folder "%~dp2" not found &Pause &Exit /B 2) Else (2>nul Del "%~dpnx1")
Set /A n=-1
For /f "usebackq tokens=1* delims=:" %%i IN (`FindStr /I /R /N /C:"^:%~1$" "%~dpnx0"`) Do Set /A n=%%i
If %n% LSS 0 (Echo List "%~1" not found &Pause &Exit /B 2)
For /f "usebackq delims=" %%s IN (`More +%n% "%~dpnx0"`) Do (
Echo "%%s"|>nul Find /I ":@S"&&(Pause &Exit /B)
>>"%~2" Echo %%s
)
Pause
Exit /B

:@S1
C:\Program Files\1 skjhdk kslhjdljsl sl;djl;jlsjd.txt
C:\Program Files\Advanced IP Scanner\2 sslm jds;ll; dalj;al lajl;akjsl;ka.png
C:\Program Files (x86)\3 aklljalkjs akjslkajlasjl akljlakjljs.dbf

:@S2
C:\Program Files\4 adSA SDASD DADADD.xls
C:\Program Files (x86)\5 aSDFDSA CSAS SAASAS.doc

:@S12345
8 adSA SDASD DADADD.xls
9 aSDFDSA CSAS SAASAS.doc

:@S3
C:\Program Files (x86)\6 adSA SDASD DADADD.xls
C:\Program Files\7 aSDFDSA CSAS SAASAS.doc

Имя списка и выходной файл передаются в аргументах.




© OSzone.net 2001-2012