Como você percorre cada linha em um arquivo de texto usando um arquivo em lotes do Windows?

244

Gostaria de saber como percorrer cada linha em um arquivo de texto usando um arquivo em lotes do Windows e processar cada linha de texto em sucessão.

Mr. Kraus
fonte

Respostas:

304

As postagens abaixo ajudaram bastante, mas não fizeram o que eu disse na minha pergunta, onde eu precisava processar a linha inteira como um todo. Aqui está o que eu achei para trabalhar.

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

A palavra-chave tokens com um asterisco (*) puxará todo o texto da linha inteira. Se você não colocar o asterisco, ele puxará apenas a primeira palavra da linha. Suponho que tenha a ver com espaços.

Para comando no TechNet

Aprecio todas as postagens!


Se houver espaços no caminho do arquivo, você precisará usar usebackq. Por exemplo.

for /F "usebackq tokens=*" %%A in ("my file.txt") do [process] %%A
Mr. Kraus
fonte
37
Uma pequena adição: para fazer isso funcionar da linha de comando interativamente, substitua %%Apor %Ano comando acima. Caso contrário, você receberá %%A was unexpected at this time..
Vadipp 12/11/2012
16
Para sua informação, se você precisar executar um comando com várias linhas, depois de "DO", poderá colocar um parêntese aberto "(" e algumas linhas depois, terminar com um parêntese próximo ")" - e você pode simplesmente colocar seu código bloquear dentro deles (recuado ao seu gosto).
precisa saber é o seguinte
3
Obrigado por esse padrão. Descobri que não posso colocar aspas (") em torno do nome do arquivo - Para nomes de arquivos com espaços, apenas me dá o nome do arquivo. Por exemplo for /F "tokens=*" %%A in ("myfile.txt") do echo A = %%A-> A = myfile.txt. Alguma idéia de como impedir isso?
será
1
Verifique se o arquivo que você está trabalhando está codificado em ANSI ou UTF8. Eu estava coçando a cabeça por que isso não estava funcionando até que tentei visualizar o arquivo usando o comando TYPE e a saída não era o que eu esperava. Nesse ponto, notei que o arquivo havia sido codificado em "UCS-2 BE BOM" por algum motivo!
Dan Stevens
1
Vale ressaltar que o parâmetro index no seu loop deve ser um único caractere. Por exemplo, %% i está bom, mas o índice %% falhará.
Vincent
59

Na referência de linha de comando do Windows:

Para analisar um arquivo, ignorando as linhas comentadas, digite:

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

Este comando analisa cada linha no Myfile.txt, ignorando as linhas que começam com ponto e vírgula e passando o segundo e o terceiro token de cada linha para o corpo FOR (os tokens são delimitados por vírgulas ou espaços). O corpo da instrução FOR faz referência a% i para obter o segundo token,% j para obter o terceiro token e% k para obter todos os tokens restantes.

Se os nomes de arquivo que você fornecer contiverem espaços, use aspas ao redor do texto (por exemplo, "Nome do arquivo"). Para usar aspas, você deve usar usebackq. Caso contrário, as aspas são interpretadas como definindo uma sequência literal para análise.

A propósito, você pode encontrar o arquivo de ajuda da linha de comando na maioria dos sistemas Windows em:

 "C:\WINDOWS\Help\ntcmds.chm"
Cinza
fonte
8
para esclarecer o "para usar aspas, você deve usar usebackq" : for /f "usebackq" %%a in ("Z:\My Path Contains Spaces\xyz\abc.txt")
drzaus
35

Em um arquivo em lotes, você DEVE usar em %%vez de %: (tipo 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

O que isso faz: O comando "do call: process %% i %% j %% k" no final do comando for passa as informações adquiridas no comando for do myfile.txt para a "sub-rotina" do processo.

Ao usar o comando for em um programa em lote, é necessário usar o dobro de sinais de% para as variáveis.

As linhas a seguir passam essas variáveis ​​do comando for para a sub-rotina do processo e permitem processar essas informações.

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

Eu tenho alguns usos bastante avançados dessa configuração exata que eu gostaria de compartilhar se mais exemplos forem necessários. Adicione seu EOL ou Delims conforme necessário, é claro.

user332474
fonte
27

Melhorando a primeira resposta "FOR / F ..": O que eu tinha que fazer era chamar executar todos os scripts listados em MyList.txt, por isso funcionou para mim:

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

--OR, se você deseja fazer isso através da linha múltipla:

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

Edit: O exemplo dado acima é para executar o loop FOR no prompt de comando; a partir de um script em lote, é necessário adicionar uma% extra, como mostrado abaixo:

---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---
Yogesh Mahajan
fonte
21

@ A resposta de MrKraus é instrutiva. Além disso, deixe-me acrescentar que, se você deseja carregar um arquivo localizado no mesmo diretório que o arquivo em lotes, prefixe o nome do arquivo com% ~ dp0. Aqui está um exemplo:

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

NB:: Se o nome ou diretório do seu arquivo (por exemplo, meuarquivo.txt no exemplo acima) tiver um espaço (por exemplo, 'meu arquivo.txt' ou 'c: \ Arquivos de Programas'), use:

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

, com a palavra-chave type chamando o typeprograma, que exibe o conteúdo de um arquivo de texto. Se você não deseja sofrer a sobrecarga de chamar o comando type, deve alterar o diretório para o diretório do arquivo de texto. Observe que o tipo ainda é necessário para nomes de arquivos com espaços.

Espero que isso ajude alguém!

Marvin Thobejane
fonte
Não há necessidade de prefixar o nome do arquivo, pois o arquivo em lotes ficará na pasta atual por padrão.
foxidrive
1
@foxidrive: Ok, eu ouvi você. Embora deva-se tomar cuidado. Por exemplo, se um diretório foi alterado, ele procuraria nesse diretório em vez daquele em que o arquivo em lote está. A solução seria chamar **cd /d %~dp0**antes do loop for. Isto faria com que se você está fazendo referência a um arquivo no diretório do arquivo de lote está em Obrigado pela observação.
Marvin Thobejane
2
Thx e +1 para o typewalkaround
Halex
Não consigo resolver o problema type, tive que citar meu nome de arquivo porque ele está em um diretório diferente que contém espaços (droga Program Files). Estou recebendo um erroThe system cannot find the file `type.
scragar
1
@ Scragar, você tem a cotação certa? precisa ser um 'não um'. No meu teclado, ele está na mesma tecla que @
FrinkTheBrave
18

A resposta aceita é boa, mas tem duas limitações.
Ele deixa linhas vazias e linhas começando com;

Para ler linhas de qualquer conteúdo, você precisa da técnica de alternância de expansão com atraso.

@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
)

O Findstr é usado para prefixar cada linha com o número da linha e dois pontos, para que as linhas vazias não estejam mais vazias.

O DelayedExpansion precisa ser desativado ao acessar o %%aparâmetro, além de pontos de exclamação !e pontos de intercalação^ serão perdidos, pois eles têm significados especiais nesse modo.

Mas, para remover o número da linha, a expansão atrasada precisa estar ativada.
set "var=!var:*:=!"remove todos até o primeiro dois pontos (usando delims=:também removeria todos os dois pontos no início de uma linha, não apenas o de findstr).
O local final desativa a expansão atrasada novamente para a próxima linha.

A única limitação agora é o limite de comprimento de linha de ~ 8191, mas parece não haver maneira de superar isso.

jeb
fonte
O Win 10 não permite setlocalna linha de comando. Quando executo código no CMD, recebo! Var! em vez de espaços em branco. Como consertar?
Zimba 15/04
o limite do comprimento da linha pode ser superado dividindo o arquivo em arquivos temporários com o comprimento máximo da linha 8190 antes do processamento. Em seguida, recombinado para um arquivo.
Zimba 15/04
14

Ou você pode excluir as opções entre aspas:

FOR /F %%i IN (myfile.txt) DO ECHO %%i
Paulo
fonte
1
Dois sinais de porcentagem próximos um do outro %% são tratados como um único sinal de porcentagem em um comando (não um arquivo em lotes).
Paul
9

Aqui está um arquivo bat que escrevi para executar todos os scripts SQL em uma pasta:

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

fonte
6

Se você tem um NT-família Windows (um com cmd.execomo o shell), tente o comando FOR / F .

Michael Ratanapintha
fonte
6

O respondente aceito usando cmd.exee

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

funciona apenas para arquivos "normais". Ele falha miseravelmente com arquivos enormes.

Para arquivos grandes, pode ser necessário usar o Powershell e algo assim:

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

ou se você tiver memória suficiente:

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

Isso funcionou para mim com um arquivo de 250 MB contendo mais de 2 milhões de linhas, onde o for /F ...comando ficou bloqueado após alguns milhares de linhas.

Para as diferenças entre foreache ForEach-Object, consulte Conhecendo o ForEach e o ForEach-Object .

(créditos: Leia o arquivo linha por linha no PowerShell )

mivk
fonte
1

Exemplos modificados aqui para listar nossos aplicativos Rails no Heroku - obrigado!

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

Código completo aqui .

sendbits
fonte
Por comentário a outra pergunta acima - Você pode pular a criação / leitura de arquivo e apenas usá-lo for /f "tokens=1" %%i in ('find /v "=" heroku_apps.txt ^| find /v ".TXT" ^| findstr /r /v /c:"^$"') do...(observe a adição de ^'s usados ​​para escapar do pipe, para que ele seja passado ao fore não diretamente ao processador de comandos)
user66001
0

Para imprimir todas as linhas no arquivo de texto a partir da linha de comando (com 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!)

Funciona com espaços em branco à esquerda, linhas em branco, linhas de espaços em branco.

Testado no Win 10 CMD

Zimba
fonte
Deus tentar, mas o seu primeiro remove amostra principais ]]]de linhas, a segunda amostra cai linhas vazias e linhas iniciadas com espaço
jeb
O segundo destina-se a remover linhas em branco. O primeiro pode modificar delimsse qualquer linha do arquivo de texto começar com, ]por exemplo. substitua por um caractere que não existe ou um caractere de controle como backspace ou bell; eles não são normalmente encontrados em arquivos de texto. A razão para delims=]se remover espaços reservados criada por /nde findcomando para preservar as linhas em branco.
Zimba
@ jeb: suporte]]] problema corrigido. Consulte atualização, para imprimir todas as linhas no arquivo de texto. Também funciona no Win 10 CMD.
Zimba