Muszę okresowo uruchamiać polecenie, które zapewnia, że niektóre pliki tekstowe są przechowywane w trybie Linux. Niestety dos2unix
zawsze modyfikuje plik, co zepsułoby znaczniki czasu pliku i folderu i spowodowało niepotrzebne zapisy.
Skrypt, który piszę jest w języku Bash, więc wolałbym odpowiedzi oparte na Bash.
bash
text-processing
newlines
Adam Ryczkowski
źródło
źródło
test
przezmyfile.txt
dwa razy w swoim przykładzie, aby uniknąć nieporozumień z/usr/bin/test
.-s
aby zobaczyć wynik, musisz usunąć flagę. Ze stron-s, --quiet, --silent suppress all normal output
Jeśli celem jest uniknięcie wpływu na znacznik czasu,
dos2unix
ma opcję-k
lub--keepdate
, która zachowa ten sam znacznik czasu. Nadal będzie musiał wykonać zapis, aby utworzyć plik tymczasowy i zmienić jego nazwę, ale nie wpłynie to na twoje znaczniki czasu.Jeśli jakakolwiek modyfikacja pliku jest niedopuszczalna, możesz użyć następującego rozwiązania z tej odpowiedzi .
źródło
find ... -exec file ... | grep CRLF
dla pliku z zakończeniami linii DOS (tj. bajtów 0D 0A) „dostaniesz coś takiego:./1/dos1.txt: ASCII text, with CRLF line terminators
Jak widzisz, zawiera on rzeczywisty ciąg CRLF i dlatego dopasowuje gogrep
szukając prosty ciąg CRLF.Możesz spróbować
grep
dla kodu CRLF, ósemkowe:lub hex:
źródło
grep
użycie, ponieważ pozwala mi łatwo wyświetlić listę wszystkich takich plików w katalogugrep -lU $'\x0D' *
i przekazać dane wyjściowe doxargs
.Od wersji
7.1
dos2unix ma-i
,--info
opcja, aby uzyskać informacje na temat łamania linii. Możesz użyć samego dos2unix do przetestowania, które pliki wymagają konwersji.Przykład:
źródło
Pierwsza metoda (
grep
):Policz linie zawierające znak powrotu karetki:
Policz linie kończące się znakiem powrotu karetki:
Zazwyczaj będą one równoważne; powrót karetki we wnętrzu linii (tj. nie na końcu) jest rzadki.
Bardziej wydajny:
To jest bardziej wydajne
grep -c
musi odczytać cały plik, policzyć wszystkie wystąpienia wzorca, agrep -q
może wyjść po zobaczeniu pierwszego wystąpienia wzorca.Uwagi:
-U
opcji (tj. Użyj-cU
lub-qU
), ponieważ GNUgrep
zgaduje, czy plik jest plikiem tekstowym. Jeśli uważa, że plik jest tekstem, ignoruje znaki powrotu karetki na końcach wierszy, próbując sprawić, by$
wyrażenia regularne działały „poprawnie” - nawet jeśli wyrażenie regularne jest\r$
! Podanie-U
(lub--binary
) unieważnia zgadywanie, powodującgrep
traktowanie plików jako plików binarnych i przekazywanie danych dosłownie do mechanizmu dopasowywania, z nienaruszonymi zakończeniami CR.grep … $'\r\n' myfile.txt
, ponieważgrep
traktuje\n
jak separator wzorca. Podobnie jakgrep -E 'foo|'
linie zawierającefoo
lub łańcuch zerowy,grep $'\r\n'
szuka linii zawierających\r
lub łańcuch zerowy, a każda linia odpowiada łańcuchowi zerowemu.Druga metoda (
file
):ponieważ
file
zgłasza coś takiego:Bezpieczniejszy wariant:
gdzie
file -b
wyświetla tylko typ pliku, a nie nazwę pliku. Bez tego plik, którego nazwa zawiera znakiCRLF
, wyzwala fałszywy wynik dodatni.file - < filename
działa, nawet jeślifilename
zaczyna się od-
. Zobacz skrypt Bash: sprawdź, czy plik jest plikiem tekstowym .Uwaga: sprawdzanie danych wyjściowych
file
może nie działać w ustawieniach narodowych innych niż angielski.źródło
"$(echo -e '\r')"
je znacznie prostszym$'\r'
, choć osobiście użyłbym tego,$'\r\n'
aby zmniejszyć liczbę fałszywych trafień.grep $'\r\n'
wydaje się pasować do wszystkich plików w moim systemie ...grep -U $'\r$'
zapobiec próbom odgadnięcia końcagrep
linii.-q
aby ustawić kod powrotu, jeśli zostanie znalezione dopasowanie, zamiast tego-c
wymaga dodatkowego sprawdzenia. Osobiście podoba mi się twoje drugie rozwiązanie, chociaż jest w dużym stopniu zależne od kaprysówfile
i może nie działać w nieanglojęzycznych lokalizacjach.Posługiwać się
cat -A
Teraz, jeśli ten plik został utworzony w systemach * NIX, zostanie wyświetlony
Ale jeśli ten plik został utworzony w systemie Windows, zostanie wyświetlony
^M
reprezentujeCR
i$
reprezentujeLF
. Zauważ, że Windows nie zapisał ostatniego wierszaCRLF
To również nie zmienia zawartości pliku.
źródło
-A
kotu. Jedną wskazówką byłoby użycie,cat -A file | less
jeśli plik jest zbyt duży. Jestem pewien, że nierzadko trzeba sprawdzać zakończenia pliku dla szczególnie długiego pliku. (Naciśnij,q
aby wyjść mniej)funkcja bash dla Ciebie:
Następnie możesz robić takie rzeczy jak
źródło
isDosFile()
w npstreamFile() { sed 's/\r$//' "$1" ; }
.Jeśli plik ma zakończenia linii CR-LF w stylu DOS / Windows, to jeśli spojrzysz na nie za pomocą narzędzia uniksowego, zobaczysz znaki CR („\ r”) na końcu każdej linii.
To polecenie:
wydrukuje,
filename
jeśli plik zawiera jedną lub więcej linii z zakończeniami w stylu Windows, i nie wydrukuje nic, jeśli nie będzie. Tyle, że^M
musi to być dosłowny znak powrotu karetki, zwykle wprowadzany w terminalu, wpisując Ctrl+, Va następnie Enter (lub Ctrl+, Va następnie Ctrl+ M). Powłoka bash pozwala napisać dosłowny znak powrotu karetki jako$'\r'
( udokumentowany tutaj ), dzięki czemu możesz napisać:Inne powłoki mogą zapewniać podobną funkcję.
Zamiast tego możesz użyć innego narzędzia:
Spowoduje to wyjście ze statusem
1
(ustawienie$?
na1
), jeśli plik zawiera jakieś zakończenia linii w stylu Windows, oraz ze statusem0
jeśli nie, co czyni go przydatnym wif
instrukcji powłoki (zauważ brak[
nawiasów]
):Plik może zawierać mieszaninę zakończeń linii w stylu Unix i Windows. Zakładam, że chcesz wykryć pliki, które mają dowolne zakończenia linii w stylu Windows.
źródło
$'\r'
, jak wspomniano w innych odpowiedziach na to pytanie.Użyj
file
:źródło
Używałem
który wydaje się działać. Uważam, że wynik jest nieco łatwiejszy do odczytania niż
Jest to również przydatne, jeśli nie możesz zainstalować
dos2unix
z jakiegoś powodu.źródło