Comandi batch di Windows per leggere la prima riga dal file di testo


85

Come posso leggere la prima riga da un file di testo utilizzando un file batch di Windows? Poiché il file è di grandi dimensioni, voglio occuparmi solo della prima riga.


1
Prova l'utility "head" GNU32. Non pensare che quello che stai cercando sarà facilmente realizzato da solo DOS Batch.
Nasir

@Nasir, non può essere fatto con un comando integrato?
Prajwal Dhatwalia

Risposte:


48

Ecco un file batch generico per stampare le prime nrighe da un file come l' headutilità GNU , invece di una singola riga.

@echo off

if [%1] == [] goto usage
if [%2] == [] goto usage

call :print_head %1 %2
goto :eof

REM
REM print_head
REM Prints the first non-blank %1 lines in the file %2.
REM
:print_head
setlocal EnableDelayedExpansion
set /a counter=0

for /f ^"usebackq^ eol^=^

^ delims^=^" %%a in (%2) do (
        if "!counter!"=="%1" goto :eof
        echo %%a
        set /a counter+=1
)

goto :eof

:usage
echo Usage: head.bat COUNT FILENAME

Per esempio:

Z:\>head 1 "test file.c"
; this is line 1

Z:\>head 3 "test file.c"
; this is line 1
    this is line 2
line 3 right here

Attualmente non conta le righe vuote. È inoltre soggetto alla limitazione della lunghezza della riga del file batch di 8 KB.


11
FYI: "GOTO: EOF" Questa è un'etichetta speciale che uscirà dallo script senza dover definire un'etichetta speciale ": exit". È anche utile quando si definiscono le subroutine nel batch (cosa dici? Subroutines? Sì)
Steven

4
Questo sembra bombardare i miei diversi file di testo GB ... Su un file mi ha dato un errore "Memoria esaurita" quando ho provato a restituire 10 righe, sull'altro file ha restituito solo una singola riga vuota quando gli ho chiesto di tornare 10 righe. Qualche idea sul perché questo accada?
Dan

1
@ Dan - Quanto sono lunghe le file? FOR / F "ignora" le righe più lunghe di 8191 byte. Ma mi chiedo se l'errore "Memoria esaurita" si verifichi se incontra una linea molto lunga.
dbenham

@StephanMuller - Vedi il mio commento a Dan sopra
dbenham

Come scritto, questa risposta ignorerà le righe vuote. Ignorerà anche le righe che iniziano con un punto ;e virgola , il carattere predefinito EOL FOR / F. Se si richiedono 10 righe, verranno stampate le prime 10 righe che non sono vuote e non iniziano con ;.
dbenham

225

eh? imo questo è molto più semplice

  set /p texte=< file.txt  
  echo %texte%

16
+1, Questo è il migliore quando funziona :-) Ha i seguenti limiti 1) Lunghezza massima della linea di 1021 byte, escluso EOL. 2) Il file deve utilizzare lo stile Windows EOL di CarriageReturn LineFeed. 3) I caratteri di controllo
finali verranno rimossi

5
Inoltre, texte dovrebbe essere esplicitamente indefinito prima di leggere il file nel caso in cui la prima riga sia vuota.
dbenham

Ecco alcuni suggerimenti extra per tagliare la corda. echo %texte:~3%per esempio salterà i primi tre caratteri. Questo è utile quando leggi un file UTF-8 con BOM.
KargWare

22

Uh ragazzi ...

C:\>findstr /n . c:\boot.ini | findstr ^1:

1:[boot loader]

C:\>findstr /n . c:\boot.ini | findstr ^3:

3:default=multi(0)disk(0)rdisk(0)partition(1)\WINNT

C:\>

2
Se il file ha più di 11 righe ne stamperà più della prima, come: 1 :, 11 :, 21 :, ecc ...
Cesar Romero

1
Buona cattura Cesar! Cerco sempre di evitare le virgolette perché mi danno fastidio, ma in questo caso è stata una cattiva idea. Per risolvere il problema, cambia findstr "^1:"e ottieni il calore e la protezione delle virgolette doppie. Oppure, se disprezzi le citazioni come me e vuoi vivere pericolosamente, usafindstr /b 1:
Amit Naidu

4
se lo vuoi senza virgolette e senza l'opzione / b poi basta fuggire il cursore: findstr ^^1.
dbenham

Ottimo suggerimento dbenham, l'escape in cmd mi sfugge sempre. A proposito, non utilizzare questo metodo per file di grandi dimensioni, in realtà legge l'intero file ed è molto inefficiente. I miei unici criteri per questa soluzione erano A) Dovrebbe essere una singola riga B) Dovrebbe essere facile da ricordare o ricreare dalla memoria e digitare, non copia-incolla C) Nessuno strumento esterno. La set /psoluzione è molto più efficiente per file di grandi dimensioni.
Amit Naidu

2
Inoltre, antepone il numero di riga alla riga di testo che desideri effettivamente! Quindi non così utile quando hai solo bisogno del testo.
Ross Presser

11

Potresti provare:

@echo off

for /f %%a in (sample.txt) do (
  echo %%a
  exit /b
)

modifica Oppure, supponi di avere quattro colonne di dati e desideri dalla quinta riga fino in fondo, prova questo:

@echo off

for /f "skip=4 tokens=1-4" %%a in (junkl.txt) do (
  echo %%a %%b %%c %%d
)

1
Questo mi ha dato l'indizio di cui avevo bisogno, ma non era del tutto corretto. Non sono sicuro di quale fosse la procedura corretta, ma ho incorporato questa soluzione nella soluzione finale. vedi stackoverflow.com/questions/130116#130209
Jesse Vogt

2
Il problema di questa soluzione è che delimita lo spazio invece che la nuova riga e non puoi avere un nome file con spazi. Puoi risolvere questi problemi con le opzioni delims e usebackq nel ciclo for.
indiv

Ha funzionato per me, ma ho dovuto aggiungere "delims="per stampare i nomi completi delle cartelle insieme agli spazi.
GChuf


4

Basandosi leggermente sulle risposte di altre persone. Ora permettendoti di specificare il file da cui vuoi leggere e la variabile in cui vuoi inserire il risultato:

@echo off
for /f "delims=" %%x in (%2) do (
set %1=%%x
exit /b
)

Ciò significa che puoi usare quanto sopra in questo modo (supponendo che tu lo chiami getline.bat)

c:\> dir > test-file
c:\> getline variable test-file
c:\> set variable  
variable= Volume in drive C has no label.

3

Una riga, utile per il reindirizzamento stdout con ">":

@for /f %%i in ('type yourfile.txt') do @echo %%i & exit

2

Prova questo

@echo off
setlocal enableextensions enabledelayedexpansion
set firstLine=1
for /f "delims=" %%i in (yourfilename.txt) do (
    if !firstLine!==1 echo %%i
    set firstLine=0
)
endlocal

2

Per Cicle un file ( file1.txt, file1[1].txt, file1[2].txt, etc.):

START/WAIT C:\LAERCIO\DELPHI\CICLADOR\dprCiclador.exe C:\LAERCIUM\Ciclavel.txt

rem set/p ciclo=< C:\LAERCIUM\Ciclavel.txt:
set/p ciclo=< C:\LAERCIUM\Ciclavel.txt

rem echo %ciclo%:
echo %ciclo%

Ed è in esecuzione.


La spiegazione di ciò è: set /pchiede tramite un prompt; tuttavia con il reindirizzamento del file <ottiene immediatamente il contenuto del file al prompt; e poiché la prima riga termina con una riga che termina, a quel punto il prompt interrompe la lettura e quindi memorizza solo la prima riga nella variabile.
sdbbs

1

Il problema con le EXIT /Bsoluzioni, quando più realisticamente all'interno di un file batch come solo una parte di esso, è il seguente. Non vi è alcuna elaborazione successiva all'interno del suddetto file batch dopo l'estensione EXIT /B. Di solito c'è molto di più nei batch oltre al solo compito limitato.

Per contrastare questo problema:

@echo off & setlocal enableextensions enabledelayedexpansion
set myfile_=C:\_D\TEST\My test file.txt
set FirstLine=
for /f "delims=" %%i in ('type "%myfile_%"') do (
  if not defined FirstLine set FirstLine=%%i)
echo FirstLine=%FirstLine%
endlocal & goto :EOF

(Tuttavia, i cosiddetti personaggi velenosi saranno ancora un problema.)

Maggiori informazioni sull'argomento di ottenere una particolare riga con i comandi batch:

Come ottengo l'ennesima, la prima e l'ultima riga di un file di testo? " Http://www.netikka.net/tsneti/info/tscmd023.htm

[Aggiunto il 28 agosto 2012] Si può anche avere:

@echo off & setlocal enableextensions
set myfile_=C:\_D\TEST\My test file.txt
for /f "tokens=* delims=" %%a in (
  'type "%myfile_%"') do (
    set FirstLine=%%a& goto _ExitForLoop)
:_ExitForLoop
echo FirstLine=%FirstLine%
endlocal & goto :EOF

Il set / p texte = <file.txt è probabilmente la soluzione più ingegnosa che è stata presentata. In questo thread di @Spaceballs. In generale, scriverei set / p "texte" = <"file.txt" ma non è questo il punto. Si noti che anche questa soluzione è soggetta a problemi di carattere veleno, cioè potrebbe non riuscire a seconda di cosa contiene il file.txt.
Timo Salmi


0

Un altro modo

setlocal enabledelayedexpansion
@echo off
for /f "delims=" %%i in (filename.txt) do (
if 1==1 (
set first_line=%%i
echo !first_line!
goto :eof
))

2
Consiglierei di utilizzare un file .bat SOLO come ultima risorsa. Se tutto ciò è possibile, cerca sempre di utilizzare un linguaggio di scripting "reale": Powershell, WSH, Python ... QUALCOSA tranne i file .bat.
paulsm4

2
Il batch non è poi così male (quando sai, cosa fai; lo stesso di ogni altra lingua). hhay: il tuo codice non funziona.
Stephan

perché non utilizzi l'espansione ritardata
Stephan

1
@ paulsm4: Cosa c'è che non va nei file batch? Funziona su tutte le versioni di Windows e ha una caratteristica unica chiamata delayedexpansion, che consente alla magia di accadere senza installare software di terze parti, purché tu lo comprenda. Sapevi di poter utilizzare TCP / IP con file DOS e batch molto prima di Powershell e dotNet?
Zimba

0

Ecco una soluzione alternativa utilizzando powershell:

powershell (Get-Content file.txt)[0]

(Puoi leggere facilmente anche una serie di righe con powershell (Get-Content file.txt)[0..3])

Se è necessario impostare una variabile all'interno di uno script batch come prima riga, file.txtè possibile utilizzare:

for /f "usebackq delims=" %%a in (`powershell ^(Get-Content file.txt^)[0]`) do (set "head=%%a")

Powershell è molto lento
Anic17

-1

for /f "delims=" %a in (downing.txt) do echo %a & pause>nul

Stampa la prima riga, quindi attende che l'utente prema un tasto per stampare la riga successiva. Dopo aver stampato le righe richieste, premere Ctrl + C per interrompere.

@Ross Presser: questo metodo stampa solo le righe, non antepone i numeri di riga.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.