คุณค้นหาไฟล์ที่มีจุดสิ้นสุดบรรทัด 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

Anticom: คุณถูกต้องในกรณีนี้ว่าความแตกต่างระหว่าง "และ" นั้นไม่เกี่ยวข้องกันอย่างไรก็ตามโดยทั่วไปแล้วจะมีความแตกต่างกันเนื่องจาก "สตริงที่ล้อมรอบนั้นอ่อนและ" มีการยกมาอย่างชัดเจน สิ่งที่ใหญ่ที่สุดที่ฉันใช้ประโยชน์คือการขยาย $ หรือ `` อย่าขยายในสตริงที่ยกมาที่อ่อนแอ ดูbash-hackers เกี่ยวกับการอ้างถึงข้อมูลเพิ่มเติม
bschlueter

4
วิธีที่ง่ายที่สุดคือการใช้ที่ทันสมัยdos2unixมี-icสวิทช์ สำหรับไฟล์ LF คุณอาจค้นหาด้วย -icunix2dos ไม่แก้ไขไฟล์ รายงานเท่านั้น
gavenkoa

3
ตั้งแต่นี้เป็นคำตอบที่ด้านบนสำหรับคำถามใด ๆ เกี่ยวกับปลายสายของ Windows / ผลตอบแทนการขนส่งบน Linux ผมคิดว่ามันคุ้มค่าสังเกตว่าคุณสามารถเห็นพวกเขาในขั้วที่มีคำสั่งcat -v somefile.txt; แสดงเป็น^M
user5359531

คำตอบ:


122

ใช้Ctrl+ V, Ctrl+ Mเพื่อป้อนอักขระ Carriage Return ตามตัวอักษรลงในสตริง grep ของคุณ ดังนั้น:

grep -IUr --color "^M"

จะใช้งานได้ - หาก^Mมี CR ตามตัวอักษรที่คุณป้อนตามที่ฉันแนะนำ

หากคุณต้องการรายชื่อไฟล์คุณต้องการเพิ่ม-lตัวเลือกด้วย

คำอธิบาย

  • -I ละเว้นไฟล์ไบนารี
  • -Uป้องกันไม่ให้ grep ตัดอักขระ CR โดยค่าเริ่มต้นจะทำได้หากตัดสินใจว่าเป็นไฟล์ข้อความ
  • -r อ่านไฟล์ทั้งหมดภายใต้แต่ละไดเร็กทอรีแบบวนซ้ำ

3
ในฐานะที่เป็นแฮ็คด่วนที่ใช้งานได้ แต่ฉันคิดว่าโซลูชันการอ่านของมนุษย์จะเป็น: grep $ '\ r' / bash shell เท่านั้น / หรือ grepprintf '\r'
akostadinov

5
@akostadinov +1 แต่ backticks ถูกตีความจากความคิดเห็นของคุณ) ตัวเลือกที่สองจะกล่าวอีกนัยหนึ่งgrep $(printf '\r')คือ $'\r'แต่สำหรับการใช้งานที่เกี่ยวข้องกับการปฏิบัติมากที่สุดทุบตีผมจะติดกับ
jankes

3
หมายเหตุ: ตัวเลือก-Uนี้เกี่ยวข้องกับ Windows (หรือ cygwin) เท่านั้น แต่ก็สำคัญมาก ใน Windows คำสั่งจะไม่ทำงานหากไม่มีคำสั่งนั้น
sleske

3
จุดของตัวเลือก-Iคืออะไร? ตามคู่มือสำหรับฉันแล้วดูเหมือนว่าไฟล์ไบนารีจะถือว่าไม่ตรงกัน การรวมกันของ-Iและ-U(ซึ่งบังคับใช้ประเภทไบนารี) ไม่ควรส่งผลให้ไฟล์ทั้งหมดถูกพิจารณาว่าไม่ตรงกันหรือ
Jānis Elmeris

3
คุณพูดถึงแฟล็ก '-l' เป็นตัวเลือกเสริม แต่ฉันคิดว่าควรรวมไว้ในคำตอบหลักเนื่องจากคำถามถามถึงรายการไฟล์เป็นหลัก นอกจากนี้ยังส่งผลให้การค้นหาเร็วขึ้น
arr_sea

170

grep อาจไม่ใช่เครื่องมือที่คุณต้องการสำหรับสิ่งนี้ มันจะพิมพ์บรรทัดสำหรับทุกบรรทัดที่ตรงกันในทุกไฟล์ ถ้าคุณไม่ต้องการเช่นเรียกใช้ todos 10 ครั้งในไฟล์ 10 บรรทัด grep ไม่ใช่วิธีที่ดีที่สุดในการดำเนินการ การใช้ find เพื่อเรียกใช้ไฟล์ในทุกไฟล์ในโครงสร้างจากนั้น grepping สำหรับ "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'
Tim Abell

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" (ดูรายการรหัสที่รองรับ )
Sean Gugler

5
การทุบตีนี้เฉพาะหรือไม่? ควรสังเกตว่าเป็นอย่างไร
cubuspl42

สำหรับ git ที่มี autocrlf ไม่ดีฉันจะใช้: grep -IUlrZ $ '\ r' | xargs -0 sed -zbi 's / \ r // g'
buzard

17

หาก 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 ใน unix มันให้การเข้ารหัสอักขระของไฟล์พร้อมกับตัวยุติบรรทัด

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

1

ถ้าเช่นฉันยูนิกซ์แบบเรียบง่ายของคุณไม่มี niceties เช่นคำสั่งไฟล์และแบ็กสแลชในนิพจน์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

การปรับเปลี่ยนที่คุณอาจต้องการดำเนินการข้างต้น ได้แก่ :

  • ปรับแต่งคำสั่งfindเพื่อค้นหาเฉพาะไฟล์ที่คุณต้องการสแกน
  • เปลี่ยนคำสั่งdumpเป็นodหรือยูทิลิตี้การถ่ายโอนไฟล์ใด ๆ ที่คุณมี
  • ยืนยันว่าคำสั่งcutมีทั้งช่องว่างนำหน้าและต่อท้ายเช่นเดียวกับเอาต์พุตอักขระเลขฐานสิบหกจากยูทิลิตี้การถ่ายโอนข้อมูล
  • จำกัดเอาต์พุตดัมพ์ไว้ที่ 1,000 อักขระแรกหรือมากกว่านั้นเพื่อประสิทธิภาพ

ตัวอย่างเช่นสิ่งนี้อาจใช้ได้กับคุณโดยใช้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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.