Как вы проходите через каждую строку в текстовом файле, используя пакетный файл Windows?

244

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

Мистер краус
источник

Ответы:

305

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

for /F "tokens=*" %%A in (myfile.txt) do [process] %%A

Ключевое слово токены со звездочкой (*) вытянет весь текст для всей строки. Если вы не введете звездочку, она будет тянуть только первое слово в строке. Я предполагаю, что это связано с пробелами.

Для командования на TechNet

Я ценю все посты!


Если в пути к файлу есть пробелы, вам нужно использовать usebackq. Например.

for /F "usebackq tokens=*" %%A in ("my file.txt") do [process] %%A
Мистер краус
источник
37
Незначительное дополнение: чтобы сделать эту работу из командной строки в интерактивном режиме , замените %%Aс %Aв команде выше. В противном случае вы получите %%A was unexpected at this time..
vadipp
17
К вашему сведению, если вам нужно сделать многострочную команду, после «DO» вы можете поставить открывающую скобку »(« и несколькими строками позже, завершите ее закрывающей скобкой ») - и вы можете просто поставить свой код блок внутри тех (с отступом на ваш вкус).
BrainSlugs83
3
Спасибо за этот шаблон. Я обнаружил, что не могу поставить кавычки (") вокруг имени файла - для имен файлов с пробелами просто дается мне имя файла. Например for /F "tokens=*" %%A in ("myfile.txt") do echo A = %%A-> A = myfile.txt. Есть идеи, как это помешать?
будет
1
Убедитесь, что файл, который вы работаете, закодирован в ANSI или UTF8. Я почесал голову, почему это не сработало, пока не попытался просмотреть файл с помощью команды TYPE, а вывод оказался не тем, чего я ожидал. В этот момент я заметил, что файл по какой-то причине был закодирован в "UCS-2 BE BOM"!
Дэн Стивенс
1
Стоит отметить, что параметр index в вашем цикле должен быть одним символом. Так, например, %% i в порядке, но индекс %% завершится ошибкой.
Винсент
59

Из справки командной строки Windows:

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

for /F "eol=; tokens=2,3* delims=," %i in (myfile.txt) do @echo %i %j %k

Эта команда анализирует каждую строку в Myfile.txt, игнорируя строки, начинающиеся с точки с запятой и передавая второй и третий токены из каждой строки в тело FOR (токены разделяются запятыми или пробелами). Тело оператора FOR ссылается на% i, чтобы получить второй токен,% j, чтобы получить третий токен, и% k, чтобы получить все оставшиеся токены.

Если имена файлов, которые вы вводите, содержат пробелы, используйте кавычки вокруг текста (например, «Имя файла»). Чтобы использовать кавычки, вы должны использовать usebackq. В противном случае кавычки интерпретируются как определение литеральной строки для анализа.

Кстати, вы можете найти файл справки командной строки в большинстве систем Windows по адресу:

 "C:\WINDOWS\Help\ntcmds.chm"
ясень
источник
8
для уточнения «использовать кавычки, вы должны использовать usebackq» : for /f "usebackq" %%a in ("Z:\My Path Contains Spaces\xyz\abc.txt")
drzaus
35

В пакетном файле вы ДОЛЖНЫ использовать %%вместо %: (Тип help for)

for /F "tokens=1,2,3" %%i in (myfile.txt) do call :process %%i %%j %%k
goto thenextstep
:process
set VAR1=%1
set VAR2=%2
set VAR3=%3
COMMANDS TO PROCESS INFORMATION
goto :EOF

Что это делает: «do call: process %% i %% j %% k» в конце команды for передает информацию, полученную в команде for из myfile.txt, в «process» «подпрограмму».

Когда вы используете команду for в пакетной программе, вам нужно использовать двойные знаки% для переменных.

В следующих строках эти переменные передаются из команды for в подпрограмму процесса и позволяют обрабатывать эту информацию.

set VAR1=%1
 set VAR2=%2
 set VAR3=%3

У меня есть довольно продвинутые способы использования этой точной настройки, которыми я хотел бы поделиться, если понадобятся дополнительные примеры. Добавьте в EOL или Delims по мере необходимости, конечно.

user332474
источник
27

Улучшение первого ответа «FOR / F ..»: мне нужно было вызвать execute каждый скрипт, указанный в MyList.txt, чтобы он работал для меня:

for /F "tokens=*" %A in  (MyList.txt) do CALL %A ARG1

- ИЛИ, если вы хотите сделать это в несколько строк:

for /F "tokens=*" %A in  (MuList.txt) do (
ECHO Processing %A....
CALL %A ARG1
)

Изменить: приведенный выше пример для выполнения цикла FOR из командной строки; из пакетного скрипта необходимо добавить дополнительный%, как показано ниже:

---START of MyScript.bat---
@echo off
for /F "tokens=*" %%A in  ( MyList.TXT) do  (
   ECHO Processing %%A.... 
   CALL %%A ARG1 
)
@echo on
;---END of MyScript.bat---
Йогеш Махаджан
источник
21

@ MrKraus ответ поучителен. Далее, позвольте мне добавить, что если вы хотите загрузить файл, расположенный в том же каталоге, что и пакетный файл, добавьте к имени файла префикс% ~ dp0. Вот пример:

cd /d %~dp0
for /F "tokens=*" %%A in (myfile.txt) do [process] %%A

NB :: Если ваше имя файла или каталога (например, myfile.txt в приведенном выше примере) имеет пробел (например, «my file.txt» или «c: \ Program Files»), используйте:

for /F "tokens=*" %%A in ('type "my file.txt"') do [process] %%A

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

Я надеюсь, что это поможет кому-то!

Марвин Тобеджейн
источник
Нет необходимости ставить префикс имени файла, так как пакетный файл будет выглядеть в текущей папке по умолчанию.
Foxidrive
1
@foxidrive: Хорошо, я вас слышу. Хотя нужно быть осторожным. Например, если каталог был изменен, он будет выглядеть в этом каталоге, а не в том, в котором находится пакетный файл. Тогда решение будет вызываться **cd /d %~dp0**перед циклом for. Это позволит убедиться, что вы ссылаетесь на файл в каталоге, в котором находится пакетный файл. Спасибо за наблюдение
Марвин Тобеджейн
2
Thx и +1 для typeWalkaround
запасного
Я не могу получить typeработу вокруг, мне пришлось процитировать мое имя файла, потому что оно находится в другом каталоге, который содержит пробелы (Черт возьми Program Files). Я получаю сообщение об ошибкеThe system cannot find the file `type.
scragar
1
@ scragar, у тебя есть правильная цитата? это должно быть "не". На моей клавиатуре она находится на той же клавише, что и @
FrinkTheBrave
18

Принятый ответ хорош, но имеет два ограничения.
Он пропускает пустые строки и строки, начинающиеся с;

Чтобы прочитать строки любого контента, вам нужна техника переключения с отложенным расширением.

@echo off
SETLOCAL DisableDelayedExpansion
FOR /F "usebackq delims=" %%a in (`"findstr /n ^^ text.txt"`) do (
    set "var=%%a"
    SETLOCAL EnableDelayedExpansion
    set "var=!var:*:=!"
    echo(!var!
    ENDLOCAL
)

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

DelayedExpansion должен быть отключен при доступе к %%aпараметру, иначе восклицательные знаки !и каретки ^будут потеряны, так как они имеют особое значение в этом режиме.

Но для удаления номера строки из строки необходимо включить отложенное расширение.
set "var=!var:*:=!"удаляет все до первого двоеточия (использование delims=:удаляет также все двоеточия в начале строки, а не только один из findstr).
Endlocal снова отключает отложенное расширение для следующей строки.

Единственным ограничением в настоящее время является ограничение длины линии ~ 8191, но, кажется, нет способа преодолеть это.

Джеб
источник
Win 10 не позволяет setlocalв командной строке. Когда я запускаю код на CMD, я получаю! Var! вместо пробелов. Как исправить?
Зимба
Предел длины строки может быть преодолен путем разделения файла на временные файлы с максимальной длиной строки 8190 перед обработкой. Затем рекомбинируется в один файл.
Зимба
14

Или вы можете исключить опции в кавычках:

FOR /F %%i IN (myfile.txt) DO ECHO %%i
Павел
источник
1
Два знака процента рядом друг с другом %% обрабатываются как один знак процента в команде (не командный файл).
Пол
9

Вот файл bat, который я написал для выполнения всех сценариев SQL в папке:

REM ******************************************************************
REM Runs all *.sql scripts sorted by filename in the current folder.
REM To use integrated auth change -U <user> -P <password> to -E
REM ******************************************************************

dir /B /O:n *.sql > RunSqlScripts.tmp
for /F %%A in (RunSqlScripts.tmp) do osql -S (local) -d DEFAULT_DATABASE_NAME -U USERNAME_GOES_HERE -P PASSWORD_GOES_HERE -i %%A
del RunSqlScripts.tmp

источник
6

Если у вас есть NT-семейства Windows (один с в cmd.exeкачестве оболочки), попробуйте команду FOR / F .

Майкл Ратанапинта
источник
6

Принятый ответ cmd.exeи использование и

for /F "tokens=*" %F in (file.txt) do whatever "%F" ...

работает только для "нормальных" файлов. Это терпит неудачу с огромными файлами.

Для больших файлов вам может понадобиться использовать Powershell и что-то вроде этого:

[IO.File]::ReadLines("file.txt") | ForEach-Object { whatever "$_" }

или если у вас достаточно памяти:

foreach($line in [System.IO.File]::ReadLines("file.txt")) { whatever "$line" } 

Это сработало для меня с файлом размером 250 МБ, содержащим более 2 миллионов строк, где for /F ...команда застряла после нескольких тысяч строк.

Различия между foreachи ForEach-Objectсм. В разделах Знакомство с ForEach и ForEach-Object .

(Авторы: Читать файл построчно в PowerShell )

mivk
источник
1

Модифицированные примеры, чтобы перечислить наши приложения Rails на Heroku - спасибо!

cmd /C "heroku list > heroku_apps.txt"
find /v "=" heroku_apps.txt | find /v ".TXT" | findstr /r /v /c:"^$" > heroku_apps_list.txt
for /F "tokens=1" %%i in (heroku_apps_list.txt) do heroku run bundle show rails --app %%i

Полный код здесь .

sendbits
источник
В комментариях к другому вопросу выше - вы можете пропустить создание / чтение файла и просто использовать for /f "tokens=1" %%i in ('find /v "=" heroku_apps.txt ^| find /v ".TXT" ^| findstr /r /v /c:"^$"') do...(обратите внимание на добавление ^символов, используемых для выхода из канала, чтобы они передавались в, forа не напрямую в командный процессор)
user66001
0

Чтобы напечатать все строки в текстовом файле из командной строки (с delayedExpansion):

set input="path/to/file.txt"

for /f "tokens=* delims=[" %i in ('type "%input%" ^| find /v /n ""') do (
set a=%i
set a=!a:*]=]!
echo:!a:~1!)

Работает с ведущими пробелами, пустыми строками, пробелами.

Проверено на Win 10 CMD

Zimba
источник
Бог попробует, но ваш первый пример удаляет ведущие ]]]из строк, второй образец отбрасывает пустые строки и строки, начинающиеся с пробела
Джеб
Второй предназначен для удаления пустых строк. 1-й можно изменить, delimsесли любые строки в текстовом файле начинаются с, ]например. заменить на некоторый символ, который не делает, или управляющий символ, такой как backspace или bell; они обычно не встречаются в текстовых файлах. Причина delims=]заключается в удалении заполнителей , созданные /nиз findкоманды , чтобы сохранить пустые строки.
Зимба
@jeb: скобка]]] проблема исправлена. Смотрите обновление, чтобы распечатать все строки в текстовом файле. Работает на Win 10 CMD тоже.
Зимба