Comando (s) por lotes de Windows para leer la primera línea del archivo de texto

84

¿Cómo puedo leer la primera línea de un archivo de texto usando un archivo por lotes de Windows? Dado que el archivo es grande, solo quiero ocuparme de la primera línea.

Jesse Vogt
fuente
1
Prueba la utilidad GNU32 "head". No crea que lo que busca se logrará fácilmente con solo DOS Batch.
Nasir
@Nasir, ¿no se puede hacer con un comando incorporado?
Prajwal Dhatwalia,

Respuestas:

48

Aquí hay un archivo por lotes de uso general para imprimir las nlíneas superiores de un archivo como la headutilidad GNU , en lugar de una sola línea.

@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

Por ejemplo:

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

Actualmente no cuenta líneas en blanco. También está sujeto a la restricción de longitud de línea de archivo por lotes de 8 KB.

indiv
fuente
10
FYI: "GOTO: EOF" Esa es una etiqueta especial que saldrá del script sin tener que definir una etiqueta especial ": salir". También es útil al definir subrutinas en el lote (¿qué es lo que dices? ¿Subrutinas? Sí)
Steven
4
Esto parece bombardear mis archivos de texto de varios GB ... En un archivo me dio un error de "Memoria insuficiente" al intentar devolver 10 líneas, en el otro archivo solo devolvió una sola línea en blanco al pedirle que regresara 10 líneas. ¿Alguna idea de por qué sucede esto?
Dan
1
@Dan - ¿Qué tan largas son las líneas? FOR / F "ignora" las líneas de más de 8191 bytes. Pero me pregunto si el error "Memoria insuficiente" surge si se encuentra con una fila realmente larga.
dbenham
@StephanMuller - Vea mi comentario a Dan arriba
dbenham
Como está escrito, esta respuesta ignorará las líneas vacías. También ignorará las líneas que comienzan con un punto y coma ;, el carácter predeterminado de FOR / F EOL. Si solicita 10 líneas, imprimirá las primeras 10 líneas que no están vacías y no comienzan con ;.
dbenham
224

uh? imo esto es mucho más simple

  set /p texte=< file.txt  
  echo %texte%
Spaceballs
fuente
16
+1, esto es lo mejor cuando funciona :-) Tiene los siguientes límites 1) Longitud máxima de línea de 1021 bytes, sin incluir EOL. 2) El archivo debe utilizar el estilo de Windows EOL de CarriageReturn LineFeed. 3) Los caracteres de control
finales se eliminarán
4
Además, texte debe estar explícitamente indefinido antes de leer el archivo en caso de que la primera línea esté en blanco.
dbenham
A continuación se ofrecen algunos consejos adicionales para recortar el hilo. echo %texte:~3%por ejemplo, omitirá los primeros tres caracteres. Eso es útil cuando está leyendo un archivo UTF-8 con BOM.
KargWare
22

Uh chicos ...

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:\>
Amit Naidu
fuente
2
Si el archivo tiene más de 11 líneas se imprimirá más que la primera, como: 1 :, 11 :, 21 :, etc ...
Cesar Romero
1
¡Buena atrapada Cesar! Siempre trato de evitar las comillas porque me molestan, pero en este caso fue una mala idea. Para arreglar, cambiar findstr "^1:"y ganar la calidez y protección de las comillas dobles. O, si desprecia las citas como yo y quiere vivir peligrosamente, usefindstr /b 1:
Amit Naidu
4
si lo desea, sin comillas y sin la opción / b continuación, sólo escapar el símbolo de intercalación: findstr ^^1.
dbenham
Gran pista dbenham, el escape en cmd siempre se me escapa. Por cierto, no utilice este método para archivos grandes, en realidad lee todo el archivo y es muy ineficaz. Mi único criterio para esta solución fue A) Debería ser una sola línea B) Debería ser fácil de recordar o recrear desde la memoria y escribir, no copiar y pegar C) Sin herramientas externas. La set /psolución es mucho más eficiente para archivos grandes.
Amit Naidu
2
Además, antepone el número de línea a la línea de texto que realmente desea. Por lo tanto, no es tan útil cuando solo necesita el texto.
Ross Presser
11

Podrías probar esto:

@echo off

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

editar O, digamos que tiene cuatro columnas de datos y desea desde la quinta fila hacia abajo, intente esto:

@echo off

for /f "skip=4 tokens=1-4" %%a in (junkl.txt) do (
  echo %%a %%b %%c %%d
)
Ross Fuhrman
fuente
1
Esto me dio la pista que necesitaba, pero no estaba del todo bien. No estoy seguro de cuál fue el procedimiento adecuado, pero incorporé esta solución a la solución final. ver stackoverflow.com/questions/130116#130209
Jesse Vogt
2
El problema de esta solución es que delimita el espacio en lugar de la nueva línea, y no puede tener un nombre de archivo con espacios. Puede solucionar estos problemas con las opciones delims y usebackq en el bucle for.
indiv
Me funcionó, pero tuve que agregar "delims="para imprimir los nombres completos de las carpetas junto con los espacios.
GChuf
4

Construyendo ligeramente sobre las respuestas de otras personas. Ahora le permite especificar el archivo desde el que desea leer y la variable en la que desea que se coloque el resultado:

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

Esto significa que puede usar lo anterior así (asumiendo que lo llamó getline.bat)

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

Una línea, útil para la redirección estándar con ">":

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

Prueba esto

@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
Sarath Avanavu
fuente
1

El problema con las EXIT /Bsoluciones, cuando es más realista dentro de un archivo por lotes como solo una parte, es el siguiente. No hay procesamiento posterior dentro de dicho archivo por lotes después del EXIT /B. Por lo general, los lotes son mucho más que una sola tarea limitada.

Para contrarrestar ese 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

(Sin embargo, los llamados personajes venenosos seguirán siendo un problema).

Más sobre el tema de obtener una línea en particular con comandos por lotes:

¿Cómo obtengo la enésima, la primera y la última línea de un archivo de texto? " Http://www.netikka.net/tsneti/info/tscmd023.htm

[Agregado el 28 de agosto de 2012] También se puede tener:

@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
Timo Salmi
fuente
El set / p texte = <file.txt es probablemente la solución más ingeniosa que se ha presentado. En este hilo de @Spaceballs. En general, escribiría set / p "texte" = <"file.txt" pero eso no viene al caso. Tenga en cuenta que incluso esta solución es propensa a los problemas de caracteres venenosos, es decir, puede fallar dependiendo de lo que contenga el archivo.txt.
Timo Salmi
1

Para Cicle un archivo ( 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%

Y está funcionando.

Laercio
fuente
La explicación de esto es: set /ppregunta mediante un mensaje; sin embargo, con la redirección de archivos <, obtiene inmediatamente el contenido del archivo cuando se le solicita; y como la primera línea termina con un final de línea, en ese punto el indicador deja de leer y, por lo tanto, almacena solo la primera línea de la variable.
sdbbs
0

Tenga en cuenta que los enfoques de archivos por lotes se limitarán al límite de línea para el procesador de comandos de DOS; consulte ¿Cuál es el límite de longitud de la línea de comando? .

Entonces, si intenta procesar un archivo que tiene líneas de más de 8192 caracteres, el script simplemente los omitirá ya que el valor no se puede retener.

kevinjansz
fuente
0

De otra manera

setlocal enabledelayedexpansion
@echo off
for /f "delims=" %%i in (filename.txt) do (
if 1==1 (
set first_line=%%i
echo !first_line!
goto :eof
))
hhay
fuente
2
Recomendaría usar un archivo .bat SOLAMENTE como último recurso. Si es posible, intente siempre utilizar un lenguaje de programación "real": Powershell, WSH, Python ... CUALQUIER COSA menos archivos .bat.
paulsm4
2
Lote no es que malo (cuando se sabe, lo que haces; mismo que con cualquier otro idioma). hhay: tu código no funciona.
Stephan
porque no utiliza la expansión retrasada
Stephan
1
@ paulsm4: ¿Qué pasa con los archivos por lotes? Funciona en todas las versiones de Windows y tiene una función única llamada expansión retardada, que permite que la magia suceda sin instalar software de terceros, siempre que lo entienda. ¿Sabía que podía utilizar TCP / IP con DOS y archivos por lotes mucho antes que Powershell y dotNet?
Zimba
0

Aquí hay una solución que usa powershell:

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

(También puede leer fácilmente un rango de líneas con powershell (Get-Content file.txt)[0..3])

Si necesita establecer una variable dentro de un script por lotes como primera línea file.txt, puede usar:

for /f "usebackq delims=" %%a in (`powershell ^(Get-Content file.txt^)[0]`) do (set "head=%%a")
mmj
fuente
Powershell es muy lento
Anic17
-1

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

Imprime la primera línea, luego espera a que el usuario presione una tecla para imprimir la siguiente línea. Después de imprimir las líneas requeridas, presione Ctrl + C para detener.

@Ross Presser: este método solo imprime líneas, no antepone números de línea.

Zimba
fuente