Як шукати файли, що містять закінчення dos-рядків (CRLF) з grep в Linux?


126

Я хочу шукати файли, що містять закінчення dos-рядків з grep в Linux. Щось на зразок цього:

grep -IUr --color '\r\n' .

Наведене вище, здається, відповідає буквальному, rnщо не є бажаним.

Вихід цього буде прокладений через xargs в todos для перетворення crlf в lf, як це

grep -IUrl --color '^M' . | xargs -ifile fromdos 'file'

2
Ви пробували dos2unix ? Він автоматично фіксує закінчення рядків.
sblundy

Я не зовсім впевнений, але в iirc є різниця між цитуванням шаблону всередині "і". Afaik у шаблонах, укладених у "послідовності втечі, інтерпретуються як правильний рядок, тому" \ r "було б еквівалентно" \\ r "і" \ r "не має еквівалента (принаймні, у цій нотації) з".
Anticom

Антиком: Ви в цьому випадку правильні, що різниця між "і" не має значення, однак, як правило, вони чітко виражені як "оточені рядки є слабкими котируванням" і "сильними цитатами". Найбільше, чим я користуюся, - це те, що $ розширення або `` не розширюються слабкими котируються рядками. Додаткову інформацію див. У хакерських хакерах .
bschlueter

4
Найпростіший спосіб - це використовувати сучасний dos2unixз -icкомутатором. Для файлів LF ви можете шукати за допомогою unix2dos -ic. Він не змінює файли. Лише доповідь.
gavenkoa

3
оскільки це найкраща відповідь на будь-яке запитання щодо закінчень / повернень каретки Windows в Linux, я вважаю, що варто зауважити, що ви можете бачити їх у терміналі за допомогою команди cat -v somefile.txt; вони відображаються як^M
user5359531

Відповіді:


121

За допомогою клавіш Ctrl+ V, Ctrl+ Mвведіть буквальний символ повернення каретки у греп-рядок. Так:

grep -IUr --color "^M"

буде працювати - якщо ^M є буквальний CR, який ви вводите, як я запропонував.

Якщо ви хочете список файлів, ви хочете додати його -l параметр.

Пояснення

  • -I ігнорувати бінарні файли
  • -Uзапобігає відшаровуванню для зняття символів CR За замовчуванням це зробить, якщо він вирішить, що це текстовий файл.
  • -r рекурсивно читати всі файли в кожному каталозі.

3
Як швидкий злом, який би спрацював, але я думаю, що людським рішенням для читання буде: grep $ '\ r' / bash shell / / grepprintf '\r'
akostadinov

5
@akostadinov +1, але зворотній зв'язок був інтерпретований з вашого коментаря;) Другим варіантом, іншими словами, буде grep $(printf '\r'). Але я б дотримувався більшості практичних застосувань, що включають баш $'\r'.
jankes

3
Примітка. Цей варіант -Uактуальний лише для Windows (або cygwin), але там він є критичним. У Windows команда не буде працювати без неї.
sleske

3
У чому сенс варіанту -I? У посібнику мені здається, що двійкові файли вважаються невідповідними. Чи не повинно поєднання -Iта -U(що примушує двійковий тип) призводити до того, що всі файли вважаються невідповідними?
Яніс Елмеріс

3
Ви згадуєте прапор '-l' як додатковий варіант, але я думаю, він повинен бути включений у основну відповідь, оскільки питання, по суті, запитує список файлів. Також це призводить до більш швидкого пошуку.
arr_sea

168

grep, мабуть, не є інструментом, який ви хочете для цього. Він надрукує рядок для кожного відповідного рядка у кожному файлі. Якщо ви не хочете, скажімо, запускати Todos 10 разів на 10-рядковому файлі, grep - це не найкращий спосіб зробити це. Використовуючи find для запуску файлу на кожному файлі в дереві, а потім проходження через "CRLF" отримає вам один рядок виводу для кожного файлу, який має закінчення рядків стилю dos:

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

отримає вам щось на кшталт:

./1/dos1.txt: ASCII text, with CRLF line terminators
./2/dos2.txt: ASCII text, with CRLF line terminators
./dos.txt: ASCII text, with CRLF line terminators

Я б уже зламав це, але все одно дякую. grep -IUrl --color '^M' . | xargs -ifile fromdos 'file'
Тім Абелл

5
Опція -l grep вказує на те, що вона просто перераховує файли (один раз), а не списки відповідностей у кожному файлі.
pjz

8
Не вдале рішення залежати від поведінки fileпрограми (без документації, орієнтованої на споживання людиною) . Це дуже крихко. Наприклад (лише один) приклад: він не працює з XML-файлами, fileзвітами XML document textнезалежно від типу нових рядків.
leonbloy

1
@leonbloy, варіант, здається, є малим регістром -m /dev/nullу мого find (GNU findutils) 4.4.2(Ubuntu 12.04).
EarlCrapstone

8
Мені подобається ця відповідь найкраще. Я просто зробивfind . -type f | xargs file | grep CRLF
brianz

58

11
Дякую! Для наочності тих, хто приходить після цього, посібник з bash говорить, що "Слова форми $ 'string" обробляються спеціально. Слово розширюється на рядок, а символи, котрі відхиляються від косої лінії, замінюються, як визначено стандартом ANSI C ". (див. також цей список підтримуваних кодів )
Шон Гуглер

5
Так це специфічно для башти? Слід зазначити, чи є.
cubuspl42

для git з погано autocrlf, я б використовував: grep -IUlrZ $ '\ r' | xargs -0 sed -zbi 's / \ r // g'
buzard

16

Якщо ваша версія grep підтримує опцію -P (--perl-regexp) , тоді

grep -lUP '\r$'

може бути використаний.


8
# list files containing dos line endings (CRLF)

cr="$(printf "\r")"    # alternative to ctrl-V ctrl-M

grep -Ilsr "${cr}$" . 

grep -Ilsr $'\r$' .   # yet another & even shorter alternative

3

Запит був пошук ... У мене схожа проблема ... хтось подав змішані закінчення рядка в контроль версій, тож тепер у нас є купа файлів із 0x0d 0x0d 0x0aзакінченнями рядків. Зауважте, що

grep -P '\x0d\x0a'

знаходить усі рядки, тоді як

grep -P '\x0d\x0d\x0a'

і

grep -P '\x0d\x0d'

не знаходить жодних рядків, тому може бути щось інше, що відбувається в grep, якщо мова йде про шаблони закінчення рядків ... на жаль для мене!


3

Ви можете використовувати командні файли в unix. Це дає вам кодування символів файлу разом з термінаторами рядків.

$ file myfile
myfile: ISO-8859 text, with CRLF line terminators
$ file myfile | grep -ow CRLF
CRLF  

1

Якщо, як і я, ваш мінімалістський unix не включає в себе делікатеси, такі як команда файлу , і зворотні косої риси у ваших виразах grep просто не співпрацюють, спробуйте це:

$ for file in `find . -type f` ; do
> dump $file | cut -c9-50 | egrep -m1 -q ' 0d| 0d'
> if [ $? -eq 0 ] ; then echo $file ; fi
> done

Зміни, які ви можете внести до вищезазначеного, включають:

  • підкрутити знахідку щоб знайти лише ті файли, які потрібно сканувати
  • змінити команду dump на od або будь-яку утиліту, яку ви маєте
  • підтвердити, що команда cut включає в себе як провідний, так і кінцевий простір, а також лише шістнадцятковий вихід символу з дампа утиліти
  • обмежте вихідний дамп на перші 1000 символів або близько того для ефективності

Наприклад, щось подібне може працювати для вас, використовуючи od замість дампа :

 od -t x2 -N 1000 $file | cut -c8- | egrep -m1 -q ' 0d| 0d|0d$'

1

dos2unix має опцію інформації про файл, яку можна використовувати для показу файлів, які будуть перетворені:

dos2unix -ic /path/to/file

Щоб зробити це рекурсивно ви можете використовувати bash«s globstarваріанту, який для поточної оболонки включений з shopt -s globstar:

dos2unix -ic **      # all files recursively
dos2unix -ic **/file # files called “file” recursively

Ви також можете використовувати findдля цього:

find -exec dos2unix -ic {} +            # all files recursively
find -name file -exec dos2unix -ic {} + # files called “file” recursively
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.