आप लिनक्स पर grep के साथ डॉस लाइन एंडिंग (CRLF) युक्त फ़ाइलों की खोज कैसे करते हैं?


126

मैं लिनक्स पर grep के साथ डॉस लाइन एंडिंग वाली फाइलों को खोजना चाहता हूं। कुछ इस तरह:

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

उपरोक्त शाब्दिक के लिए मैच लगता है rnजो वांछित नहीं है।

इस के उत्पादन को xargs के माध्यम से पाइप में डाला जाएगा ताकि इस तरह से एलएफ को समतल रूपांतरित किया जा सके

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

2
क्या आपने dos2unix आज़माया है ? यह स्वचालित रूप से लाइन अंत को ठीक करता है।
sblundy

मुझे पूरा यकीन नहीं है, लेकिन iirc के अंदर के पैटर्न को कोट करने के बीच एक अंतर है 'और' '। एफिक सीक्वेंस में वर्णित पैटर्न में Afaik को उचित स्ट्रिंग के रूप में व्याख्या किया गया है, इसलिए' \ r '"\\ r" और "के बराबर होगा।" \ r "का कोई समकक्ष (कम से कम उस संकेतन में) 'के साथ नहीं है।
एंटीकॉम

एंटीकॉम: आप इस मामले में सही हैं कि 'और "के बीच का अंतर अप्रासंगिक है; हालांकि, आमतौर पर वे अलग-अलग होते हैं क्योंकि' घिरे तार कमजोर उद्धृत होते हैं, और" मजबूत उद्धृत होते हैं। सबसे बड़ी बात मैं इसका फायदा उठाता हूं कि $ एक्सपैंशन या `` कमजोर उद्धृत स्ट्रिंग्स में विस्तार नहीं करते हैं। अधिक के लिए उद्धृत करने पर बैश-हैकर्स देखें ।
bschlueter

4
सबसे आसान तरीका स्विच के dos2unixसाथ आधुनिक का उपयोग -icकरना है। LF फ़ाइलों के लिए आप unix2dos के साथ खोज कर सकते हैं -ic। यह फ़ाइलों को संशोधित नहीं करता है। केवल रिपोर्ट।
गवेंको

3
चूंकि यह लिनक्स पर विंडोज लाइन एंडिंग / कैरिज रिटर्न के बारे में किसी भी प्रश्न के लिए एक शीर्ष उत्तर है, मुझे लगता है कि यह ध्यान देने योग्य है कि आप उन्हें कमांड के साथ टर्मिनल में देख सकते हैंcat -v somefile.txt ; वे के रूप में दिखाई^M
user5359531

जवाबों:


121

Ctrl+ का उपयोग करें V, Ctrl+ Mएक शाब्दिक कैरिज वापसी चरित्र अपने grep स्ट्रिंग में प्रवेश करने के लिए। इसलिए:

grep -IUr --color "^M"

काम करेगा - अगर ^Mवहाँ एक शाब्दिक सीआर है कि आप इनपुट के रूप में मैंने सुझाव दिया है।

यदि आप फ़ाइलों की सूची चाहते हैं, तो आप -lविकल्प भी जोड़ना चाहते हैं ।

व्याख्या

  • -I बाइनरी फ़ाइलों को अनदेखा करें
  • -UCR अक्षर छीनने के लिए grep को रोकता है। डिफ़ॉल्ट रूप से यह ऐसा होगा यदि यह निर्णय लेता है कि यह एक पाठ फ़ाइल है।
  • -r प्रत्येक निर्देशिका के तहत सभी फ़ाइलों को पुनरावर्ती रूप से पढ़ें।

3
एक त्वरित हैक के रूप में जो काम करेगा लेकिन मुझे लगता है कि मानव रीडबेल समाधान होगा: grep $ '\ r' / bash शेल केवल / या grepprintf '\r'
akostadinov

5
@akostadinov +1, लेकिन बैकटिक्स को आपकी टिप्पणी से बाहर निकाला गया;) दूसरा विकल्प, दूसरे शब्दों में, होगा grep $(printf '\r')। लेकिन ज्यादातर व्यावहारिक उपयोगों के लिए बैश को शामिल किया जाता है, मैं इसके साथ रहना चाहूंगा $'\r'
15

3
नोट: विकल्प -Uकेवल विंडोज (या साइबरविन) के लिए प्रासंगिक है, लेकिन यह वहां महत्वपूर्ण है। विंडोज पर, कमांड इसके बिना काम नहीं करेगा।
sleske

3
विकल्प का क्या मतलब है -I? मैनुअल के द्वारा, यह मुझे लगता है कि बाइनरी फ़ाइलों को गैर-मिलान माना जाता है। चाहिए नहीं के संयोजन -Iऔर -Uपरिणाम (जो बाइनरी प्रकार लागू) में सभी फाइलों मेल नहीं खाने वाले के रूप में माना जा रहा है?
जानिस एल्मरिस

3
आप एक ऐड-ऑन विकल्प के रूप में '-l' झंडे का उल्लेख करते हैं, लेकिन मुझे लगता है कि इसे प्राथमिक उत्तर में शामिल किया जाना चाहिए क्योंकि प्रश्न अनिवार्य रूप से फाइलों की एक सूची के लिए पूछता है। इसके अलावा, यह एक तेजी से खोज में परिणाम है।
arr_sea

168

grep शायद वह उपकरण नहीं है जो आप इसके लिए चाहते हैं। यह हर फाइल में हर मैचिंग लाइन के लिए एक लाइन प्रिंट करेगा। जब तक आप कहना न चाहें, 10 लाइन फ़ाइल पर 10 बार टॉडोस चलाएं, grep इसके बारे में जाने का सबसे अच्छा तरीका नहीं है। पेड़ में हर फ़ाइल पर फ़ाइल चलाने का उपयोग करें फिर "CRLF" के लिए उस के माध्यम से grepping आपको प्रत्येक फ़ाइल के लिए आउटपुट की एक पंक्ति मिलेगी जिसमें डॉस स्टाइल लाइन अंत है:

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
Grep के लिए -l विकल्प इसे प्रत्येक फ़ाइल में मैचों को सूचीबद्ध करने के बजाय केवल फाइलों (एक बार) को सूचीबद्ध करने के लिए कहता है।
pjz

8
एक अच्छा समाधान नहीं है, उस पर निर्भर करने के लिए (अनैच्छिक, मानव उपभोग के लिए उन्मुख) fileकार्यक्रम का व्यवहार । यह बहुत नाजुक है। उदाहरण के लिए (सिर्फ एक): यह XML फ़ाइलों के साथ काम नहीं करता है, नए प्रकार की परवाह किए बिना fileरिपोर्ट करता है XML document text
leonbloy

1
@leonbloy, विकल्प -m /dev/nullमेरे find (GNU findutils) 4.4.2(Ubuntu 12.04) पर एक लोअरकेस लगता है ।
अर्लक्रैपस्टोन

8
मुझे यह उत्तर सबसे अच्छा लगता है। मैंने बस कियाfind . -type f | xargs file | grep CRLF
ब्रैनज़

58

11
धन्यवाद! बाद में आने वालों की स्पष्टता के लिए, बैश मैनुअल कहते हैं, "फॉर्म $ 'स्ट्रिंग' के शब्दों को विशेष रूप से व्यवहार किया जाता है। शब्द स्ट्रिंग में फैलता है, बैकस्लैश-एस्कैप्ड अक्षरों के साथ एएनएसआई सी मानक द्वारा निर्दिष्ट के रूप में प्रतिस्थापित किया जाता है।" ( समर्थित कोड्स की इस सूची को भी देखें )
सीन गुगलर

5
तो क्या यह बैश-विशिष्ट है? यह ध्यान दिया जाना चाहिए अगर यह है।
क्यूबसप्ले 42

बुरी तरह से आटोक्रॉफ्ट के साथ git के लिए, मैं उपयोग करूँगा: 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

आप यूनिक्स में फ़ाइल कमांड का उपयोग कर सकते हैं। यह आपको लाइन टर्मिनेटर के साथ फाइल का कैरेक्टर एन्कोडिंग देता है।

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

1

अगर, मेरी तरह, आपके न्यूनतम यूनिक्स में फ़ाइल कमांड जैसी बारीकियां शामिल नहीं हैं , और आपके 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

संशोधन आप ऊपर शामिल करना चाहते हैं शामिल कर सकते हैं:

  • केवल उन फ़ाइलों को खोजने के लिए जो आप स्कैन करना चाहते हैं , खोजने के लिए खोज कमांड को ट्वीक करें
  • डंप कमांड को od या जो भी फाइल डंप यूटिलिटी है, उसे बदलें
  • पुष्टि करें कि कट कमांड में एक अग्रणी और अनुगामी स्थान और साथ ही डंप उपयोगिता से हेक्साडेसिमल वर्ण आउटपुट दोनों शामिल हैं
  • दक्षता के लिए डंप आउटपुट को पहले 1000 वर्णों तक सीमित करें

उदाहरण के लिए, ऐसा कुछ आपके लिए डंप के बजाय od का उपयोग करने के लिए काम कर सकता है :

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

1

dos2unix एक फ़ाइल जानकारी विकल्प है जिसका उपयोग उन फ़ाइलों को दिखाने के लिए किया जा सकता है जिन्हें परिवर्तित किया जाएगा:

dos2unix -ic /path/to/file

रिकर्सिवली आप उपयोग कर सकते हैं कि ऐसा करने के लिए bashके 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 Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.