Necesito ejecutar periódicamente un comando que garantice que algunos archivos de texto se mantengan en modo Linux. Desafortunadamente, dos2unixsiempre modifica el archivo, lo que ensuciaría las marcas de tiempo del archivo y la carpeta y causaría escrituras innecesarias.
El guión que escribo está en Bash, por lo que preferiría respuestas basadas en Bash.
bash
text-processing
newlines
Adam Ryczkowski
fuente
fuente

testpormyfile.txtdos veces en su ejemplo para evitar confusiones con/usr/bin/test.-sbandera para ver la salida. De las páginas man:-s, --quiet, --silent suppress all normal outputSi el objetivo es simplemente evitar afectar la marca de tiempo,
dos2unixtiene una opción-ku--keepdateopción que mantendrá la marca de tiempo igual. Todavía tendrá que escribir para crear el archivo temporal y cambiarle el nombre, pero sus marcas de tiempo no se verán afectadas.Si alguna modificación del archivo es inaceptable, puede usar la siguiente solución de esta respuesta .
fuente
find ... -exec file ... | grep CRLFpara un archivo con terminaciones de línea de DOS (es decir, bytes 0D 0A) "obtendrá algo como:./1/dos1.txt: ASCII text, with CRLF line terminatorsComo puede ver, esto contiene la cadena CRLF real y, por lo tanto, segrepbusca buscando la cadena simple CRLF.Puede intentar el
grepcódigo CRLF, octal:o hexadecimal:
fuente
grepuso porque me permite enumerar fácilmente todos esos archivos en el directoriogrep -lU $'\x0D' *y pasarle la salidaxargs.Desde la versión
7.1dos2unix tiene una-i,--infoopción para obtener información sobre los saltos de línea. Puede usar dos2unix para probar qué archivos necesitan conversión.Ejemplo:
fuente
Primer método (
grep):Cuente las líneas que contienen un retorno de carro:
Cuente las líneas que terminan con un retorno de carro:
Estos serán típicamente equivalentes; un retorno de carro en el interior de una línea (es decir, no al final) es raro.
Más eficiente:
Esto es mas eficiente
grep -cnecesita leer todo el archivo, para contar todas las apariciones del patrón, mientras quegrep -qpuede salir al ver la primera aparición del patrón.Notas:
-Uopción (es decir, usar-cUo-qU), porque GNUgrepadivina si el archivo es un archivo de texto. Si cree que el archivo es texto, ignora los retornos de carro al final de las líneas, en un intento de hacer que$las expresiones regulares funcionen "correctamente", ¡incluso si la expresión regular lo es\r$! La especificación-U(o--binary) anula esta conjetura, logrepque hace que los archivos se traten como binarios y pasen los datos al mecanismo de coincidencia textualmente, con terminaciones CR intactas.grep … $'\r\n' myfile.txt, porque segreptrata\ncomo un delimitador de patrón. Así comogrep -E 'foo|'busca líneas que contienenfooo una cadena nula,grep $'\r\n'busca líneas que contienen\ro una cadena nula, y cada línea coincide con una cadena nula.Segundo método (
file):porque
fileinforma algo como:Variante más segura:
dónde
file -bgenera solo el tipo de archivo y no el nombre del archivo. Sin esto, un archivo cuyo nombre incluyera los caracteresCRLFprovocaría un falso positivo.file - < filenamefunciona incluso sifilenamecomienza con-. Ver Script Bash: verifica si un archivo es un archivo de texto .Tenga en cuenta que la comprobación de la salida
filepuede no funcionar en una configuración regional que no esté en inglés.fuente
"$(echo -e '\r')"por uno mucho más simple$'\r', aunque personalmente lo usaría$'\r\n'para reducir la cantidad de falsos positivos.grep $'\r\n'parece coincidir con todos los archivos en mi sistema ...grep -U $'\r$', para evitargreptratar de adivinar las terminaciones de línea.-qsimplemente establecer el código de retorno si se encuentra una coincidencia, en lugar de lo-ccual requiere una verificación adicional. Personalmente, me gusta su segunda solución, aunque depende en gran medida de los caprichosfiley podría no funcionar en un entorno no inglés.Utilizar
cat -AAhora, si este archivo se hizo en sistemas * NIX, se mostrará
Pero si este archivo se hizo en Windows, se mostrará
^MrepresentaCRy$representaLF. Observe que Windows no guardó la última línea conCRLFEsto tampoco cambia el contenido del archivo.
fuente
-Apara el gato. Un consejo, aunque sería utilizarcat -A file | lesssi el archivo es demasiado grande. Estoy seguro de que no es raro tener que verificar las terminaciones de archivos para un archivo particularmente largo. (Presioneqpara dejar menos)una función bash para ti:
Entonces puedes hacer cosas como
fuente
isDosFile()en su ejemplo:streamFile() { sed 's/\r$//' "$1" ; }.Si un archivo tiene terminaciones de línea CR-LF estilo DOS / Windows, entonces si lo mira usando una herramienta basada en Unix, verá caracteres CR ('\ r') al final de cada línea.
Este comando:
se imprimirá
filenamesi el archivo contiene una o más líneas con terminaciones de línea estilo Windows, y no imprimirá nada si no lo tiene. Excepto que^Mtiene que ser un carácter de retorno de carro literal, típicamente ingresado en la terminal escribiendo Ctrl+ Vseguido de Enter (o Ctrl+ Vy luego Ctrl+ M). El shell bash le permite escribir un retorno de carro literal como$'\r'( documentado aquí ), para que pueda escribir:Otros proyectiles pueden proporcionar una característica similar.
Puede usar otra herramienta en su lugar:
Esto saldrá con un estado de
1(configuración$?a1) si el archivo contiene cualquier final de línea al estilo de Windows, y con un estado de0si no lo hace, lo que lo hace útil en unaifdeclaración de shell (tenga en cuenta la falta de[corchetes]):Un archivo puede contener una mezcla de terminaciones de línea estilo Unix y estilo Windows. Supongo aquí que desea detectar archivos que tengan cualquier final de línea estilo Windows.
fuente
$'\r', como se menciona en otras respuestas a esta pregunta.Uso
file:fuente
he estado usando
que parece funcionar Encuentro la salida un poco más fácil de leer que
También es útil si no puede instalar
dos2unixpor alguna razón.fuente