Cómo convertir el final de línea de Windows en el final de línea de Unix (CR / LF a LF)

80

Soy un desarrollador de Java y estoy usando Ubuntu para desarrollar. El proyecto se creó en Windows con Eclipse y utiliza la codificación Windows-1252 .

Para convertir a UTF-8 he usado el programa de recodificación :

find Web -iname \*.java | xargs recode CP1252...UTF-8

Este comando da este error:

recode: Web/src/br/cits/projeto/geral/presentation/GravacaoMessageHelper.java failed: Ambiguous output in step `CR-LF..data

Lo busqué y obtuve la solución en Bash y Windows, Recode: Salida ambigua en el paso `data..CR-LF ' y dice:

Convierta los finales de línea de CR / LF a un solo LF: Edite el archivo con Vim, dé el comando :set ff=unixy guarde el archivo. Recode ahora debería ejecutarse sin errores.

Bien, pero tengo muchos archivos para eliminar el carácter CR / LF, y no puedo abrir cada uno para hacerlo. Vi no proporciona ninguna opción de línea de comandos para operaciones Bash.

¿Se puede usar sed para hacer esto? ¿Cómo?

MaikoID
fuente
recodeproduce este error al intentar recodificar un archivo con codificación de nueva línea DOS ( \r\n- CRLF) y Unix ( \nLF) mixtos . Lamentablemente fromdos, anteriormente un binario, actualmente es un alias para recodificar el que tiene este problema.
TMS
no puedes hacervim +ex_command_one +ex_command_two ... file
derekdreery
¡Asombroso! No hay awksolución en las respuestas.
Gerold Broser

Respuestas:

122

Debería haber un programa llamado dos2unixque arregle los finales de línea por usted. Si aún no está en su caja de Linux, debería estar disponible a través del administrador de paquetes.

cHao
fuente
2
He instalado tofrodos que proporcionan el comando fromdos, pero el problema persiste. fromdos -a GravacaoMessageHelper.java; recode CP1252 ... UTF-8 GravacaoMessageHelper.java devuelve: recode: GravacaoMessageHelper.java falló: Salida ambigua en el paso `CR-LF..data '
MaikoID
1
@MaikoID: Entonces tienes problemas más grandes. Recode no debería preocuparse por los finales de línea de todos modos, ya que un CR es solo otro carácter para convertir. Y no parece importarle en mi máquina.
cHao
1
fromdoses solo un alias de recode, y eso producirá el error OP mencionado en archivos con codificación DOS mixta (\ r \ n - CRLF) y unix (\ n LF). Solo dos2unixfunciona universalmente.
TMS
1
dos2unix está disponible en OS X a través de homebrew: "brew install dos2unix"
Joseph Sheedy
1
Sólo para dar seguimiento a esto, me encontré con el mismo problema y terminó usando la siguiente: find ./ -name "*.java" -exec dos2unix {} +.
amracel
85

sed no puede coincidir con \ n porque la nueva línea final se elimina antes de que la línea se coloque en el espacio del patrón, pero puede coincidir con \ r, por lo que puede convertir \ r \ n (dos) a \ n (unix) eliminando \ r

sed -i 's/\r//g' file

Advertencia: esto cambiará el archivo original

Sin embargo, no puede cambiar de unix EOL a dos o mac antiguo (\ r) con esto. Más lecturas aquí:

¿Cómo puedo reemplazar una nueva línea (\ n) usando sed?

Jichao
fuente
4
+1 ¡Esta es una buena solución! ¡Pero debes tener en cuenta que sed -icambiará el archivo original ! Debido a que la gente no esperaría sedcomportarse así, la advertencia es apropiada aquí. No mucha gente lo sabe, -iasí que lo intentarán sed -i ... file > file2y no esperarán que se modifique el archivo original.
TMS
No todas las sedvariantes reconocen la secuencia simbólica no estándar \r. Pruebe con un carácter literal ctrl-M en ese caso (en muchos shells, escriba ctrl-V ctrl-M para producir el carácter de control literal).
tripleee
14

De hecho, vim permite lo que estás buscando. Ingrese vim y escriba los siguientes comandos:

:args **/*.java
:argdo set ff=unix | update | next

El primero de estos comandos establece la lista de argumentos para cada coincidencia de archivos **/*.java, que son todos los archivos Java, de forma recursiva. El segundo de estos comandos hace lo siguiente para cada archivo en la lista de argumentos, a su vez:

  • Establece los finales de línea al estilo Unix (ya lo sabe)
  • Escribe el archivo si se ha cambiado
  • Pasa al siguiente archivo
Arandur
fuente
Esto probablemente sea mucho más lento que usarlo dos2unixen un bucle for, ¡pero aún es bueno saber cómo hacerlo en Vim!
jpaugh
2
Yo :: corazón :: mi vim. Gracias por esto.
Jono
9

El comando tr también puede hacer esto:

tr -d '\15\32' < winfile.txt > unixfile.txt

y debería estar disponible para usted.

Deberá ejecutar tr desde dentro de un script, ya que no puede funcionar con nombres de archivo. Por ejemplo, cree un archivo myscript.sh:

#!/bin/bash

for f in `find -iname \*.java`; do
    echo "$f"
    tr -d '\15\32' < "$f" > "$f.tr"
    mv "$f.tr" "$f"
    recode CP1252...UTF-8 "$f"
done

La ejecución myscript.shprocesará todos los archivos java en el directorio actual y sus subdirectorios.

KeithL
fuente
¿cómo puedo adaptarme para encontrar Web -iname * .java | xargs recode CP1252 ... UTF-8
MaikoID
Necesitaría ejecutar tr dentro de un script bash, ya que no puede funcionar con nombres de archivo. Editaré mi respuesta con un script de muestra.
KeithL
Thnx por la respuesta pero el error persiste = | Salida ambigua en el paso `CR-LF..data '
MaikoID
7

Haré una pequeña excepción a la respuesta de jichao. De hecho, puedes hacer todo lo que acaba de mencionar con bastante facilidad. En lugar de buscar un \n, simplemente busque el retorno de carro al final de la línea.

sed -i 's/\r$//' "${FILE_NAME}"

Para cambiar de unix a dos, simplemente busque el último carácter en la línea y agregue un formulario de alimentación. (Agregaré -rpara facilitar esto con expresiones regulares grep).

sed -ri 's/(.)$/\1\r/' "${FILE_NAME}"

En teoría, el archivo podría cambiarse al estilo mac agregando código al último ejemplo que también agrega la siguiente línea de entrada a la primera línea hasta que se hayan procesado todas las líneas. Sin embargo, no intentaré dar ese ejemplo aquí.

Advertencia: -i cambia el archivo real. Si desea realizar una copia de seguridad, agregue una cadena de caracteres después -i. Esto moverá el archivo existente a un archivo con el mismo nombre con tus personajes agregados al final.

John Chesshir
fuente
1
Me gusta tu sugerencia, pero solo falta una cita única de cierre. Debería ser: sed -ri 's / (.) $ / \ 1 \ r /' $ {FILE_NAME}
mgouin
1
@mgouin Gracias por señalar eso. He añadido la comilla simple que falta.
John Chesshir
1
Para convertir LF a CRLF, no es necesario capturar algún último carácter antes del final de la línea y también podría tener un impacto en el rendimiento. En mi caso es suficiente con hacer sed -i 's/$/\r/' ${FILE_NAME}...
Thomas Urban
La -ropción no es portátil; si sedno lo tiene, quizás intente -E.
tripleee
5

Para superar

Ambiguous output in step `CR-LF..data'

simplemente la solución podría ser agregar una -fbandera para forzar la conversión.

V_V
fuente
0

¿ Probaste el script de Python de Bryan Maupin que se encuentra aquí ? (Lo modifiqué un poco para que sea más genérico)

#!/usr/bin/env python

import sys

input_file_name = sys.argv[1]
output_file_name = sys.argv[2]

input_file = open(input_file_name)
output_file = open(output_file_name, 'w')

line_number = 0

for input_line in input_file:
    line_number += 1
    try:  # first try to decode it using cp1252 (Windows, Western Europe)
        output_line = input_line.decode('cp1252').encode('utf8')
    except UnicodeDecodeError, error:  # if there's an error
        sys.stderr.write('ERROR (line %s):\t%s\n' % (line_number, error))  # write to stderr
        try:  # then if that fails, try to decode using latin1 (ISO 8859-1)         
            output_line = input_line.decode('latin1').encode('utf8')
        except UnicodeDecodeError, error:  # if there's an error
            sys.stderr.write('ERROR (line %s):\t%s\n' % (line_number, error))  # write to stderr
            sys.exit(1)  # and just keep going
    output_file.write(output_line)

input_file.close()
output_file.close()

Puedes usar ese script con

$ ./cp1252_utf8.py file_cp1252.sql file_utf8.sql
Anthony O.
fuente
-1

Vuelva a Windows, dígale a Eclipse que cambie la codificación a UTF-8, luego vuelva a Unix y ejecute d2ulos archivos.

Jonathan
fuente
Aunque si hay muchos archivos, esto puede ser más trabajo del que está dispuesto a poner en él ...
Jonathan
¿Qué es d2u y dónde encontrarlo?
Jesper Rønn-Jensen
Se le cambia el nombre de vez en cuando. Parece que Ubuntu lo llama fromdosen 10.04 y es parte del paquete tofrodos.
Jonathan