Làm cách nào để xóa các ký tự không hợp lệ khỏi tên tệp?


47

Tôi có các tệp có ký tự không hợp lệ như thế này

009_-_�%86ndringshåndtering.html

Đó là một Ænơi mà một cái gì đó đã đi sai trong tên tệp.

Có cách nào để loại bỏ tất cả các ký tự không hợp lệ?

hoặc có thể trđược sử dụng bằng cách nào đó?

echo "009_-_�%86ndringshåndtering.html" | tr ???

5
Các ký tự có thể không "không hợp lệ", nếu không thì hệ thống tệp sẽ không lưu trữ chúng (trừ khi bạn đã làm điều gì đó thực sự khó chịu với FS). Bạn đã thử thay đổi ngôn ngữ của mình (ví dụ: UTF8) để hiển thị tên chính xác chưa?
James O'Gorman

Câu trả lời:


41

Một cách sẽ là với sed:

mv 'file' $(echo 'file' | sed -e 's/[^A-Za-z0-9._-]/_/g')

Thay thế filebằng tên tệp của bạn, tất nhiên. Điều này sẽ thay thế bất cứ thứ gì không phải là chữ cái, số, dấu chấm, dấu gạch dưới hoặc dấu gạch ngang bằng dấu gạch dưới. Bạn có thể thêm hoặc xóa các ký tự để giữ tùy thích và / hoặc thay đổi ký tự thay thế thành bất kỳ thứ gì khác hoặc không có gì cả.


4
Tôi đã sử dụng:f='file'; mv 'file' ${f//[^A-Za-z0-9._-]/_}
Louis

1
Hãy tìm giải pháp tốt nhất của H. Hess bên dưới ... (và bình luận hài hước của tôi bên cạnh :))
Jan Sila

31

Tôi giả sử bạn đang ở trên hộp Linux và các tệp được tạo trên hộp Windows. Linux sử dụng UTF-8 làm mã hóa ký tự cho tên tệp, trong khi Windows sử dụng thứ khác. Tôi nghĩ rằng đây là nguyên nhân của vấn đề.

Tôi sẽ sử dụng "confmv". Đây là một công cụ có thể chuyển đổi tên tệp từ mã hóa ký tự này sang mã hóa ký tự khác. Đối với Tây Âu, một trong những hoạt động bình thường này:

convmv -r -f windows-1252 -t UTF-8 .
convmv -r -f ISO-8859-1 -t UTF-8 .
convmv -r -f cp-850 -t UTF-8 .

Nếu bạn cần cài đặt nó trên Linux dựa trên Debian, bạn có thể làm như vậy bằng cách chạy:

sudo apt-get install convmv

Nó hoạt động cho tôi mọi lúc và nó phục hồi tên tệp gốc.

Nguồn: HireWebLabs


1
Điều này có vẻ đầy hứa hẹn, nhưng có ý tưởng nào để nói mã hóa là gì không? Tôi có một thư mục được gọi là Save the current file in Word 97-2004 format\sco.workflowđã được tạo trên máy Mac của tôi (thông qua Microsoft Office) và các bảng mã ở trên không có bất kỳ ảnh hưởng nào.
Sridhar Sarnobat

Thật đáng để chỉ ra rằng theo mặc định, confmv chạy ở chế độ "thử nghiệm", ở đó nó chỉ thực hiện chạy khô và cho bạn biết những tệp nào nó sẽ di chuyển. Sau đó nó sẽ bảo bạn chạy lại nó với --notesttùy chọn thực sự đổi tên các tệp.
Kenny Rasschaert

16

Tôi giả sử bạn có nghĩa là bạn muốn đi qua hệ thống tập tin và sửa tất cả các tập tin như vậy?

Đây là cách tôi làm

find /path/to/files -type f -print0 | \
perl -n0e '$new = $_; if($new =~ s/[^[:ascii:]]/_/g) {
  print("Renaming $_ to $new\n"); rename($_, $new);
}'

Điều đó sẽ tìm thấy tất cả các tệp có ký tự không phải mã ascii và thay thế các ký tự đó bằng dấu gạch dưới ( _). Tuy nhiên, hãy cẩn thận, nếu một tệp có tên mới đã tồn tại, nó sẽ ghi đè lên nó. Kịch bản có thể được sửa đổi để kiểm tra trường hợp như vậy, nhưng tôi đã không đưa nó vào để giữ cho nó đơn giản.


13

Sau câu trả lời tại https://stackoverflow.com/questions/2124010/grep-regex-to-match-non-ascii-char character , Bạn có thể sử dụng:

rename 's/[^\x00-\x7F]//g' *

nơi *phù hợp với các tập tin bạn muốn đổi tên. Nếu bạn muốn làm điều đó qua nhiều thư mục, bạn có thể làm một cái gì đó như:

find . -exec rename 's/[^\x00-\x7F]//g' "{}" \;

Bạn có thể sử dụng đối số -n renameđể thực hiện chạy khô và xem điều gì sẽ được thay đổi mà không thay đổi nó.


Có cách nào để sửa đổi điều này để giữ các ký tự nước ngoài như ü và ä chẳng hạn?
Anh Cả Geek

Chỉ có cái thứ hai làm việc cho tôi. Mọi thứ đều nằm trong cùng một thư mục nên tôi không chắc có gì khác biệt ..?
Shautieh

1
@Shautieh: -n ngăn nó thực sự chạy. Tôi sẽ làm rõ câu trả lời.
ness101

đổi tên có thể bị chậm khi xử lý nhiều tệp. Nếu bạn muốn tăng tốc độ này, hãy đẩy kiểm tra vào tìm. Tôi không chắc làm thế nào để làm điều đó mặc dù.
isaaclw

13

Tôi đã có một số tệp tiếng Nhật với tên tệp bị hỏng được khôi phục từ thanh usb bị hỏng và các giải pháp ở trên không hiệu quả với tôi.

Tôi khuyên bạn nên gói cai nghiện:

Tiện ích cai nghiện đổi tên các tệp để làm cho chúng dễ làm việc hơn. Nó loại bỏ không gian và những phiền toái khác như vậy. Nó cũng sẽ dịch hoặc dọn sạch các ký tự Latin-1 (ISO 8859-1) được mã hóa bằng ASCII 8 bit, các ký tự Unicode được mã hóa bằng UTF-8 và các ký tự thoát CGI.

Ví dụ sử dụng:

detox -r -v /path/to/your/files
-r Recurse vào thư mục con
-v Hãy tiết lộ về những tập tin đang được đổi tên 
-n Có thể được sử dụng cho chạy khô (chỉ hiển thị những gì sẽ được thay đổi)

2
Điều này sẽ cao hơn nhiều, tôi kêu gọi mọi người nên xem xét detoxtrước khi cơ bản phát minh lại bánh xe. Nếu bạn nhìn vào trang man, bạn sẽ thấy rằng nó bao gồm tất cả các giải pháp được đề xuất khác ở đây vì tính linh hoạt của nó.
emk2203

Ê-xê-chi-ên 25:17 - Phúc cho anh ấy, nhân danh từ thiện và thiện chí sẽ nâng cao giải pháp này, vì anh ấy thực sự là người giữ anh em mình và là người tìm ra những đứa trẻ bị lạc.
Jan Sila

Vô tình, con đường không thể là '.' trong debian. Nếu bạn sử dụng một '.' nó không tìm thấy gì
isaaclw

Tôi tự hỏi nếu nó thực sự hoạt động, có vẻ như loại bỏ / thay thế các ký tự Trung Quốc, ví dụ 的节奏啊, nhưng các ký tự đó là tên tệp hợp lệ.
林果

5

Kịch bản shell này vệ sinh một thư mục theo cách đệ quy, để làm cho các tệp di động giữa Linux / Windows và FAT / NTFS / exFAT. Nó loại bỏ các ký tự điều khiển /:*?"<>\|và một số tên Windows dành riêng như COM0.

sanitize() {
  shopt -s extglob;

  filename=$(basename "$1")
  directory=$(dirname "$1")

  filename_clean=$(echo "$filename" | sed -e 's/[\\/:\*\?"<>\|\x01-\x1F\x7F]//g' -e 's/^\(nul\|prn\|con\|lpt[0-9]\|com[0-9]\|aux\)\(\.\|$\)//i' -e 's/^\.*$//' -e 's/^$/NONAME/')

  if (test "$filename" != "$filename_clean")
  then
    mv -v "$1" "$directory/$filename_clean"
  fi
}

export -f sanitize

sanitize_dir() {
  find "$1" -depth -exec bash -c 'sanitize "$0"' {} \;
}

sanitize_dir '/path/to/somewhere'

Linux ít hạn chế hơn về mặt lý thuyết ( /\0bị nghiêm cấm trong tên tệp) nhưng trong thực tế, một số ký tự can thiệp vào các lệnh bash (như *...) vì vậy chúng cũng nên tránh trong tên tệp.

Các nguồn tuyệt vời để hạn chế đặt tên tệp:


1
Đó là những gì tôi tìm kiếm! nhưng thêm dấu ngoặc kép để hỗ trợ các thư mục có dấu cách tìm "$ 1" -depth -exec bash -c 'sanitize "$ 0"' {} \;
mmv-ru

1

Nếu bạn muốn xử lý các dòng mới được nhúng, các ký tự đa dòng, dấu cách, dấu gạch đầu dòng, dấu gạch chéo ngược và khoảng trắng bạn sẽ cần một cái gì đó mạnh mẽ hơn, hãy xem câu trả lời này:
https://superuser.com/a/858671/365691

Tôi đặt tập lệnh lên trên code.google.com nếu có ai quan tâm: rnf-bash-rename-script


Kịch bản được liên kết ở đây đã giải quyết vấn đề cho tôi
Jeremiah Rose

0

Tôi sử dụng một lớp lót này để xóa các ký tự không hợp lệ trong các tệp phụ đề:

for f in *.srt; do nf=$(echo "$f" |sed -e 's/[^A-Za-z0-9.-]/./g;s/\.\.\././g;s/\.\././g'); test "$f" != "$nf" && mv "$f" "$nf" && echo "$nf"; done
  1. Chỉ xử lý các tệp * .srt (* có thể được sử dụng thay cho * .srt để xử lý mọi tệp)
  2. Xóa tất cả các ký tự khác ngoại trừ các chữ cái A-Za-z, số 0-9, dấu chấm "." Và dấu gạch ngang "-"
  3. Loại bỏ thời gian gấp đôi hoặc gấp ba
  4. Kiểm tra xem tên tập tin cần thay đổi
  5. Nếu đúng, nó đổi tên tệp bằng lệnh mv, sau đó xuất ra các thay đổi mà nó đã thực hiện bằng lệnh echo

Nó hoạt động để bình thường hóa tên thư mục của phim:

for f in */; do nf=$(echo "$f" |sed -e 's/[^A-Za-z0-9.]/./g' -e 's/\.\.\././g' -e 's/\.\././g' -e 's/\.*$//'); test "$f" != "$nf" && mv "$f" "$nf" && echo "$nf"; done

Tương tự các bước như trên nhưng tôi đã thêm một lệnh sed để xóa một khoảng thời gian ở cuối thư mục

X-Men Days of Future Past (2014) [1080p]
Được sửa đổi thành:
X-Men.Days.of.Future.Past.2014.1080p


-2

cho tệp trong *; làm mv "$ file" $ (echo "$ file" | sed -e 's / [^ A-Za-z0-9. -] / / g'); làm xong &


2
Bạn nên giải thích những gì mã của bạn làm và sử dụng định dạng thích hợp. Mã của bạn có thể khiến các tệp bị xóa bằng cách giới thiệu các xung đột trong tên. Và chạy toàn bộ trong nền là loại ngớ ngẩn.
kasperd
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.