Tránh thay thế khoảng trắng khi đổi tên tập tin


10

Tôi đang cố gắng đổi tên các tệp như thế này:

for file in *;
do
mv -i "$file" "$(echo "$file" | sed -e 's/[^A-Za-z0-9._-]/_/g')";
done

Nhưng sedlệnh thay thế tất cả các không gian bằng _.

Làm cách nào tôi có thể chỉnh sửa sedlệnh để làm cho nó bao gồm các khoảng trắng cùng với các ký tự được chỉ định? Tôi đã thử sử dụng \snhưng nó không hoạt động ...

EDIT:
Ví dụ: tệp trip: hill, nên được đổi tên : trip_ hill, nhưng lệnh ở trên tạo ra nó trip__hill.


Tôi đang chuyển một số tệp từ linux sang Mac. Nhưng vì một số lý do, hệ thống Mac không thể đọc tất cả các tên tệp, vì vậy tôi đang cố gắng đổi tên các tệp của mình. Thêm một khoảng trắng cho lệnh trên không hoạt động. Và bạn đã đúng: Tôi muốn thay thế tất cả các ký tự bằng '_' ngoại trừ các ký tự được chỉ định. Và tôi không biết làm thế nào để bao gồm char không gian.

Xin lưu ý rằng tôi đang cố gắng thay thế tất cả các ký tự bằng '_' ngoại trừ các ký tự được chỉ định. Không có mẫu cụ thể nào cho các tệp được đổi tên, vì vậy tôi không thể sử dụng lệnh perl này.

Câu trả lời:


11

Đừng phân tích tên tập tin với sed! Đầu ra của echo "$file"có thể không đáng tin cậy.

Sử dụng rename. Vào ngày 17.10, bạn cần cài đặt nó trước

sudo apt install rename

Sau đó:

rename -n -- 's/[^-A-Za-z0-9_ .]/_/g' *

Ghi chú

  • loại bỏ -nsau khi thử nghiệm để thực sự đổi tên các tập tin
  • -- tùy chọn kết thúc trong trường hợp bất kỳ tệp nào bắt đầu bằng -
  • [^-A-Za-z0-9_ .]các ký tự chúng tôi không muốn thay thế - đặt -đầu tiên hoặc cuối cùng để nó không thể chỉ ra một phạm vi (nó được xử lý theo nghĩa đen ở các vị trí này).
  • Không gian có thể được bao gồm trong lớp
  • . được xử lý theo nghĩa đen (trong bối cảnh regex khác, nó đại diện cho bất kỳ nhân vật nào và cần phải thoát ra).

Điều này cũng hoạt động trong sed:

$ echo 'trip: hill' | sed 's/[^-A-Za-z0-9 _.]/_/g'
trip_ hill

Nếu tôi thêm một khoảng trắng vào cuối phiên bản của bạn, tôi sẽ gặp lỗi:

$ echo 'trip: hill' | sed -e 's/[^A-Za-z0-9._- ]/_/g'
sed: -e expression #1, char 22: Invalid range end

Nhưng -cuối cùng, nó hoạt động:

$ echo 'trip: hill' | sed -e 's/[^A-Za-z0-9._ -]/_/g'
trip_ hill

Vì vậy, có lẽ vị trí của dấu gạch nối gây ra vấn đề của bạn khi bạn thêm khoảng trắng. Nhưng lời khuyên không nên phân tích tên tập tin đứng!


Lệnh này hoạt động cảm ơn bạn. Bạn cũng đã xác định rõ các lỗi trong lệnh tôi đã sử dụng.

2
Cám ơn bạn một lần nữa. Xin lưu ý rằng không cần sử dụng dấu gạch chéo '\' trong trường hợp sử dụng sed. Bởi vì điều này thêm '\' vào danh sách các ký tự bị bỏ qua.

2
@latach Đó là một dấu gạch chéo ngược, nhưng bạn hoàn toàn đúng. Sau khi thử nghiệm và đào bới xung quanh, tôi thấy đó .là nghĩa đen trong một lớp nhân vật. TIL!
Zanna

2

Bạn cũng có thể chỉ cần sử dụng shell, mở rộng tham số của Bash có thể thay thế:

for f in ./* ; do
    mv "$f" "${f//[^-A-Za-z0-9._ ]/_}"
done

Dấu gạch chéo kép bảo nó thay thế tất cả các kết quả khớp, ngoài ra, cú pháp rất đơn giản.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.