it-swarm.com.de

Wie kann ich testen, ob eine Datei CRLF oder LF verwendet), ohne sie zu ändern?

Ich muss regelmäßig einen Befehl ausführen, der sicherstellt, dass einige Text -Dateien im Linux-Modus gehalten werden. Unglücklicherweise dos2unix ändert immer die Datei, wodurch die Zeitstempel von Dateien und Ordnern durcheinander gebracht werden und unnötige Schreibvorgänge verursacht werden.

Das Skript, das ich schreibe, ist in Bash, daher würde ich Antworten bevorzugen, die auf Bash basieren.

53
Adam Ryczkowski

Sie können dos2unix Als Filter verwenden und die Ausgabe mit der Originaldatei vergleichen:

dos2unix < myfile.txt | cmp - myfile.txt
44

Wenn das Ziel nur darin besteht, eine Beeinflussung des Zeitstempels zu vermeiden, dos2unix hat ein -k oder --keepdate Option, mit der der Zeitstempel gleich bleibt. Es muss noch geschrieben werden, um die temporäre Datei zu erstellen und umzubenennen, aber Ihre Zeitstempel sind nicht betroffen.

Wenn eine Änderung der Datei nicht akzeptabel ist, können Sie die folgende Lösung von diese Antwort verwenden.

find . -not -type d -exec file "{}" ";" | grep CRLF
26
j883376

Sie könnten versuchen, grep für CRLF-Code, oktal:

grep -U $'\015' myfile.txt

oder hex:

grep -U $'\x0D' myfile.txt
22
don_crissti

Seit Version 7.1 dos2unix hat ein -i, --info Option, um Informationen zu Zeilenumbrüchen abzurufen. Sie können dos2unix selbst verwenden, um zu testen, welche Dateien konvertiert werden müssen.

Beispiel:

dos2unix -ic *.txt | xargs dos2unix
22

Erste Methode (grep):

Zählen Sie die Zeilen, die einen Wagenrücklauf enthalten:

[[ $(grep -c $'\r' myfile.txt) -gt 0 ]] && echo dos

Zählen Sie die Zeilen, die enden mit einen Wagenrücklauf:

[[ $(grep -c $'\r$' myfile.txt) -gt 0 ]] && echo dos

Diese sind normalerweise gleichwertig; Ein Wagenrücklauf im Inneren einer Linie (d. h. nicht am Ende) ist selten.

Effizienter:

grep -q $'\r' myfile.txt && echo dos

Das ist effizienter

  1. weil es nicht erforderlich ist, die Anzahl in eine ASCII Zeichenfolge) zu konvertieren und diese Zeichenfolge dann wieder in eine Ganzzahl zu konvertieren und sie mit Null zu vergleichen, und
  2. weil grep -c die gesamte Datei lesen muss, um alle Vorkommen des Musters zu zählen, während grep -q beim ersten Auftreten des Musters beendet werden kann.

Anmerkungen:

  • In diesem Fall müssen Sie möglicherweise die Option -U hinzufügen (dh -cU oder -qU verwenden), da GNU grep errät, ob es sich bei der Datei um eine Textdatei handelt. Wenn die Datei als Textdatei betrachtet wird, werden die Zeilenumbrüche an den Zeilenenden ignoriert, um $ in zu setzen reguläre Ausdrücke funktionieren "korrekt" - auch wenn der reguläre Ausdruck \r$ ist! Die Angabe von -U (oder --binary) setzt dieses Rätselraten außer Kraft und verursacht grep, um die Datei (en) als binär zu behandeln und die Daten wörtlich mit intakten CR-Endungen an den Matching-Mechanismus zu übergeben.
  • Führen Sie grep … $'\r\n' myfile.txt nicht aus, da grep\n als Musterbegrenzer behandelt. So wie grep -E 'foo|' nach Zeilen sucht, die foo oder eine Nullzeichenfolge enthalten, sucht grep $'\r\n' nach Zeilen, die \r oder eine Nullzeichenfolge enthalten, und jede Zeile stimmt mit einer Nullzeichenfolge überein.

Zweite Methode (file):

[[ $(file myfile.txt) =~ CRLF ]] && echo dos

weil file so etwas meldet wie:

myfile.txt: UTF-8 Unicode text, with CRLF line terminators

Sicherere Variante:

[[ $(file -b - < myfile.txt) =~ CRLF ]] && echo dos

wo

Beachten Sie, dass das Überprüfen der Ausgabe von file in einem nicht englischen Gebietsschema möglicherweise nicht funktioniert.

14
BertS

Verwenden cat -A

$ cat file
hello
hello

Wenn diese Datei nun in * NIX-Systemen erstellt wurde, wird sie angezeigt

$ cat -A file
hello$
hello$

Wenn diese Datei jedoch in Windows erstellt wurde, wird sie angezeigt

$ cat -A file
hello^M$
hello

^M steht für CR und $ steht für LF. Beachten Sie, dass Windows die letzte Zeile nicht mit CRLF gespeichert hat

Dies ändert auch nicht den Dateiinhalt.

14
GypsyCosmonaut

eine Bash-Funktion für Sie:

# return 0 (true) if first line ends in CR
isDosFile() {
    [[ $(head -1 "$1") == *$'\r' ]]  
}

Dann kannst du Sachen wie machen

streamFile () {
    if isDosFile /tmp/foo.txt; then
        sed 's/\r$//' "$1"
    else
        cat "$1"
    fi
}

streamFile /tmp/foo.txt | process_lines_without_CR
4
glenn jackman

Wenn eine Datei CR-LF-Zeilenenden im DOS/Windows-Stil hat, werden am Ende jeder Zeile CR-Zeichen ('\ r') angezeigt, wenn Sie sie mit einem Unix-basierten Tool betrachten.

Dieser Befehl:

grep -l '^M$' filename

druckt filename, wenn die Datei eine oder mehrere Zeilen mit Zeilenenden im Windows-Stil enthält, und druckt nichts, wenn dies nicht der Fall ist. Abgesehen davon, dass ^M Ein wörtliches Wagenrücklaufzeichen sein muss, das normalerweise durch Eingabe in das Terminal eingegeben wird Ctrl+V gefolgt von Enter (oder Ctrl+V und dann Ctrl+M). Mit der Bash-Shell können Sie einen wörtlichen Wagenrücklauf als $'\r' ( hier dokumentiert ) schreiben, sodass Sie schreiben können:

grep -l $'\r$' filename

Andere Schalen bieten möglicherweise ein ähnliches Merkmal.

Sie können stattdessen ein anderes Tool verwenden:

awk '/\r$/ { exit(1) }' filename

Dies wird mit dem Status 1 (Setzen von $? Auf 1) Beendet, wenn die Datei Zeilenenden im Windows-Stil enthält, und mit dem Status 0 Wenn dies nicht der Fall ist, ist es in einer Shell if -Anweisung nützlich (beachten Sie das Fehlen von [ - Klammern ]):

if awk '/\r$/ { exit(1) }' filename ; then
    echo filename has Unix-style line endings
else
    echo filename has at least one Windows-style line ending
fi

Eine Datei kann eine Mischung aus Zeilenenden im Unix- und Windows-Stil enthalten. Ich gehe hier davon aus, dass Sie Dateien erkennen möchten, die beliebige Zeilenenden im Windows-Stil haben.

4
Keith Thompson

Verwenden Sie file:

$ file README.md
README.md: ASCII text, with CRLF line terminators

$ dos2unix README.md
dos2unix: converting file README.md to Unix format...

$ file README.md
README.md: ASCII text
3
Dan Sorak

Ich habe benutzt

cat -v filename.txt | diff - filename.txt

das scheint zu funktionieren. Ich finde die Ausgabe etwas leichter zu lesen als

dos2unix < filename.txt | diff - filename.txt

Es ist auch nützlich, wenn Sie dos2unix Aus irgendeinem Grund nicht installieren können.

2
Alex028502