Score:0

เหตุใดจึงเปลี่ยนชื่อไฟล์ด้วยการพิมพ์ sed และ mv '$'\r'

ธง ke

ฉันใช้ Ubuntu บนเครื่อง Windows 10 ฉันพยายามเปลี่ยนชื่อไฟล์ 5 ไฟล์ (file1.txt, file2.txt, file3.txt, file4.txt, file5.txt) เพื่อให้แต่ละไฟล์ถูกแทนที่ด้วย Sample#_VoucherID.fastq.gz

ในการทำเช่นนี้ ฉันมีไฟล์ .csv ที่มีรูปแบบเป็น ไฟล์เก่าไฟล์ใหม่ และฉันกำลังใช้ เสด ดังนี้"

sed 's/^/mv -vi /;s/,/ /;s/$//' < ไฟล์เปลี่ยนชื่อ.csv | ทุบตี -e

เมื่อใดก็ตามที่ฉันเรียกใช้สิ่งนี้ แทนที่จะได้รับ:

ตัวอย่าง#_VoucherID.fastq.gz สำหรับแต่ละไฟล์ ฉันได้รับ 'ตัวอย่าง#_VoucherID.fastq.gz'$'\r' แทน. ทำไมสิ่งนี้ถึงเกิดขึ้น? ถ้าฉันใช้ เอ็มวี ในเทอร์มินัล Ubuntu เพื่อเปลี่ยนชื่อไฟล์ ฉันได้รับการเปลี่ยนชื่อไฟล์ตามที่ฉันต้องการโดยไม่ต้องใช้ ',$,และ \ ก่อนและหลังชื่อไฟล์ ถ้าฉันไม่ใช้ | ทุบตี -e ในไฟล์และฉันลบเครื่องหมายคำพูด มันพิมพ์:

mv -vi file1.txt ตัวอย่าง 1_VoucherID.fastq.gz

mv -vi file2.txt Sample2_VoucherID.fastq.gz

mv -vi file3.txt Sample3_VoucherID.fastq.gz

mv -vi file4.txt ตัวอย่าง 4_VoucherID.fastq.gz

mv -vi file5.txt ตัวอย่าง 5_VoucherID.fastq.gz

อย่างไรก็ตาม มันไม่ได้เรียกใช้ไฟล์ เอ็มวี สั่งการ. ฉันจะเปลี่ยนชื่อไฟล์โดยไม่ได้รับอักขระพิเศษเหล่านั้นได้อย่างไร

cn flag
เนื่องจากไฟล์ File-Rename.csv มีการลงท้ายบรรทัดแบบ `\r\n` แบบ DOS ใช้ `dos2unix` กับมัน หรือทำ `sed -e 's/\r$//' -e 'your code here'`
Score:2
ธง hr

สิ่งนี้เกิดขึ้นเนื่องจากไฟล์อินพุตของคุณ ไฟล์-Rename.csv มีการลงท้ายบรรทัด CRLF แบบ Windows แทนแบบ Unix เอลฟ์ - เดอะ $'\r' เป็นวิธีของเชลล์ในการแทนอักขระการขึ้นบรรทัดใหม่

คุณสามารถ "แก้ไข" คำสั่งของคุณได้โดยเปลี่ยนนิพจน์ sed สุดท้ายจาก s/$// (ซึ่งไม่ได้ทำอะไรเลย - $ ในนิพจน์ทั่วไปคือการยืนยันความยาวเป็นศูนย์ที่ตรงกับจุดสิ้นสุดของบรรทัด แต่ไม่ได้ใช้อักขระ) ถึง s/\r$//

หรือแปลงไฟล์อินพุตโดยใช้ ดอส2ยูนิกซ์

อย่างไรก็ตาม วิธีการเปลี่ยนชื่อไฟล์นี้มีปัญหา โดยเฉพาะอย่างยิ่ง มันจะล้มเหลวหากชื่อเก่าหรือชื่อใหม่มีช่องว่างหรืออักขระพิเศษของเชลล์บางตัว และแม้แต่อนุญาตการแทรกโค้ด1. ฉันจะแนะนำสิ่งที่ชอบแทน

ในขณะที่ IFS= อ่านเก่าใหม่; ทำ 
  mv -vi -- "$เก่า" "$ใหม่"
เสร็จสิ้น < <(sed 's/\r$//' File-Rename.csv)

หรือ

ในขณะที่ IFS= อ่านเก่าใหม่; ทำ 
  echo mv -vi -- "$old" "${new%$'\r'}"
เสร็จแล้ว < File-Rename.csv

(ถอด เสียงสะท้อน เมื่อคุณพอใจกับคำสั่งที่เสนอ)

โปรดทราบว่าแนวทางนี้จะล้มเหลวเองสำหรับชื่อบางชื่อที่ถูกต้องตามกฎหมายในรูปแบบ CSV โดยเฉพาะชื่อที่มีเครื่องหมายจุลภาคฝังอยู่ในเครื่องหมายคำพูด ("ฟู บาร์" บาส ตัวอย่างเช่น).


1 คิดว่าจะเกิดอะไรขึ้นถ้ามีคนป้อนชื่อไฟล์เช่น ฟู; rm * ตัวอย่างเช่น

Justin avatar
ke flag
ขอขอบคุณ! สิ่งนี้ได้ผล! เพื่อความรู้ของฉัน `s/\r$\` ทำอะไร มันกำลังบอกว่าจะแทนที่ `CRLF` โดยไม่ทำอะไรเลยเหรอ? สิ่งนี้ได้ผล! ฉันไม่ใช้การเว้นวรรค ดังนั้นฉันจึงใช้คำแนะนำแรก แต่ฉันจะจำโค้ด ` while ' ที่คุณส่งมาด้วย ฉันรู้สึกทราบซึ้ง!
hr flag
@จัสติน ใช่ ถูกต้อง - `sed 's/\r$//'` ตรงกับอักขระการขึ้นบรรทัดใหม่ `\ r` ที่ยึดท้ายบรรทัด `$` และไม่มีอะไรมาแทนที่ คุณอาจลบการขึ้นบรรทัดใหม่ *ทั้งหมด* ได้อย่างปลอดภัย (เช่น `tr -d '\r'`) แต่เวอร์ชัน sed นั้นถูกต้องอย่างเป็นทางการมากกว่าสำหรับการเปลี่ยน `CRLF` เป็น `LF`
Justin avatar
ke flag
ขอขอบคุณ; มันมีประโยชน์จริงๆ เพราะหลายครั้งที่ฉันพยายามใช้ `dos2unix` มันไม่ได้ช่วยอะไร ดังนั้นการรู้รหัสทางเลือกอย่างที่คุณให้มานั้นดีมาก ฉันขอขอบคุณที่คุณสละเวลาอธิบายโค้ดด้วยเช่นกัน!

โพสต์คำตอบ

คนส่วนใหญ่ไม่เข้าใจว่าการถามคำถามมากมายจะปลดล็อกการเรียนรู้และปรับปรุงความสัมพันธ์ระหว่างบุคคล ตัวอย่างเช่น ในการศึกษาของ Alison แม้ว่าผู้คนจะจำได้อย่างแม่นยำว่ามีคำถามกี่ข้อที่ถูกถามในการสนทนา แต่พวกเขาไม่เข้าใจความเชื่อมโยงระหว่างคำถามและความชอบ จากการศึกษาทั้ง 4 เรื่องที่ผู้เข้าร่วมมีส่วนร่วมในการสนทนาด้วยตนเองหรืออ่านบันทึกการสนทนาของผู้อื่น ผู้คนมักไม่ตระหนักว่าการถามคำถามจะมีอิทธิพลหรือมีอิทธิพลต่อระดับมิตรภาพระหว่างผู้สนทนา