Điểm:0

Tại sao đổi tên tệp bằng sed và mv in '$'\r'

lá cờ ke

Tôi đang sử dụng Ubuntu trên máy Windows 10. Tôi đang cố đổi tên 5 tệp (tệp1.txt, tệp2.txt, tệp3.txt, tệp4.txt, tệp5.txt) để mỗi tệp được thay thế bằng Mẫu#_VoucherID.fastq.gz.

Để làm điều này, tôi có một tệp .csv có định dạng là tập tin cũ, tập tin mới và tôi đang sử dụng sed như sau"

sed 's/^/mv -vi /;s/,/ /;s/$//' < Đổi tên tệp.csv | bash -e

Bất cứ khi nào tôi chạy cái này, tôi thay vì nhận được:

Mẫu#_VoucherID.fastq.gz cho mỗi tập tin, tôi nhận được 'Sample#_VoucherID.fastq.gz'$'\r' thay thế. Tại sao chuyện này đang xảy ra? nếu tôi sử dụng mv chỉ trong thiết bị đầu cuối Ubuntu để đổi tên tệp, tôi nhận được các tệp được đổi tên theo ý muốn mà không cần ',$,và \ trước và sau tên tệp. Nếu tôi không sử dụng | bash -e trong tệp và tôi xóa dấu ngoặc kép, nó sẽ in:

mv -vi file1.txt Sample1_VoucherID.fastq.gz

mv -vi file2.txt Sample2_VoucherID.fastq.gz

mv -vi file3.txt Sample3_VoucherID.fastq.gz

mv -vi file4.txt Sample4_VoucherID.fastq.gz

mv -vi file5.txt Sample5_VoucherID.fastq.gz

tuy nhiên, nó không thực sự chạy mv chỉ huy. Làm cách nào tôi có thể đổi tên các tệp của mình mà không nhận được các ký tự thừa đó?

lá cờ cn
Bởi vì tệp File-Rename.csv có kết thúc dòng `\r\n` kiểu DOS. Sử dụng `dos2unix` trên đó hoặc làm `sed -e 's/\r$//' -e 'your code here'`
Điểm:2
lá cờ hr

Điều này xảy ra vì tệp đầu vào của bạn Đổi tên tệp.csv có kết thúc dòng CRLF kiểu Windows thay vì kiểu Unix LF - các $'\r' là cách trình bao biểu thị ký tự xuống dòng.

Bạn có thể "sửa" lệnh của mình bằng cách thay đổi biểu thức sed cuối cùng từ s/$// (mà không thực sự làm bất cứ điều gì - $ trong một biểu thức chính quy là một xác nhận có độ dài bằng 0 khớp với cuối dòng, nhưng không thực sự sử dụng một ký tự) thành s/\r$//

Ngoài ra, chuyển đổi tệp đầu vào bằng cách sử dụng dos2unix

TUY NHIÊN phương pháp đổi tên tệp này có vấn đề - đặc biệt, nó sẽ thất bại nếu tên cũ hoặc tên mới chứa khoảng trắng hoặc một số ký tự đặc biệt của hệ vỏ - và thậm chí cho phép tiêm mã1. Thay vào đó tôi muốn đề nghị một cái gì đó như

trong khi IFS=, đọc cũ mới; làm 
  mv -vi -- "$old" "$new"
xong < <(sed 's/\r$//' File-Rename.csv)

hoặc

trong khi IFS=, đọc cũ mới; làm 
  echo mv -vi -- "$old" "${new%$'\r'}"
xong < File-Rename.csv

(gỡ bỏ tiếng vang khi bạn hài lòng với các lệnh được đề xuất).

Lưu ý rằng phương pháp này sẽ tự thất bại đối với một số tên hợp pháp trong định dạng CSV - đặc biệt là những tên có chứa dấu phẩy nhúng được trích dẫn ("foo,bar",baz Ví dụ).


1 nghĩ xem điều gì sẽ xảy ra nếu ai đó nhập tên tệp như foo;rm * Ví dụ

Justin avatar
lá cờ ke
Cảm ơn bạn! Điều này đã làm việc! Theo hiểu biết của tôi, `s/\r$\` đã làm gì? Có phải nó đang nói thay thế `CRLF` bằng không? Điều này đã làm việc! Tôi không sử dụng dấu cách, vì vậy tôi đã sử dụng gợi ý đầu tiên, nhưng tôi cũng sẽ ghi nhớ mã `while` mà bạn gửi. Tôi rât cảm kich!
lá cờ hr
@Justin vâng đúng vậy - `sed 's/\r$//'` khớp với ký tự xuống dòng `\r` được neo vào cuối dòng `$` và không thay thế gì ở vị trí của nó. Bạn có thể xóa *tất cả* dấu xuống dòng một cách an toàn (ví dụ: với `tr -d '\r'`) nhưng phiên bản sed chính xác hơn để biến `CRLF` thành `LF`
Justin avatar
lá cờ ke
Cảm ơn bạn; điều đó thực sự hữu ích bởi vì nhiều lần tôi đã cố gắng sử dụng `dos2unix` nhưng nó không giúp được gì; vì vậy việc biết các mã thay thế như bạn đã cung cấp là điều tuyệt vời. Tôi cũng đánh giá cao việc bạn dành thời gian để giải thích mã!

Đăng câu trả lời

Hầu hết mọi người không hiểu rằng việc đặt nhiều câu hỏi sẽ mở ra cơ hội học hỏi và cải thiện mối quan hệ giữa các cá nhân. Ví dụ, trong các nghiên cứu của Alison, mặc dù mọi người có thể nhớ chính xác có bao nhiêu câu hỏi đã được đặt ra trong các cuộc trò chuyện của họ, nhưng họ không trực giác nhận ra mối liên hệ giữa câu hỏi và sự yêu thích. Qua bốn nghiên cứu, trong đó những người tham gia tự tham gia vào các cuộc trò chuyện hoặc đọc bản ghi lại các cuộc trò chuyện của người khác, mọi người có xu hướng không nhận ra rằng việc đặt câu hỏi sẽ ảnh hưởng—hoặc đã ảnh hưởng—mức độ thân thiện giữa những người đối thoại.