Không thể xóa / di chuyển tệp với các ký tự đặc biệt trong tên tệp


17

Như bạn có thể thấy bên dưới các tập tin có các ký tự không phổ biến.

ảnh chụp màn hình quản lý tập tin

Xóa chúng trong thiết bị đầu cuối hoặc cá heo trả về lỗi:

Không có tập tin hoặc thư mục

Chạy ls -latrên thư mục đã cho tôi đầu ra này:

-rw-rw-r--  1 aalap aalap      0 Nov 14 01:05 ??
-rw-rw-r--  1 aalap aalap      0 Nov 14 01:05 ?2?.???љ?!?Gb??σ?[?F?
-rw-rw-r--  1 aalap aalap      0 Nov 14 01:05 ??3]d???:????????1????G?p?ȋ??????嫳?d????ą-??
-rw-rw-r--  1 aalap aalap      0 Nov 14 01:05 3l??#g?w????O?JKB7?co??քH??bT?NA???S???X?I?A?qC??M?I???
-rw-rw-r--  1 aalap aalap      0 Nov 14 01:05 ??8??-?@,?Zp?[?bI????7^?ñ[?ڏ??z?O???ч??eEȰ?+??,OF??h

Tôi đã chạy một fscklệnh trên phân vùng từ một hệ điều hành khác nhưng nó không thay đổi gì cả.

Làm cách nào để xóa những tập tin này?


1
Bạn đã thiết lập hệ thống của bạn để có một thư mục nhà được mã hóa?
dobey

@dobey Tôi không có.
karjedavpalaa

5
@Panther Bạn đang nhầm. Bản thân nó không phải là một dấu hiệu của một hệ thống tệp bị hỏng và ngay cả khi nó bị gây ra bởi lỗi dữ liệu nào đó, fsck sẽ không làm gì với nó.
zwol


1
Tôi đã có các tập tin với các charaters không được nhận dạng trong tên. Đổi tên các tập tin làm việc. sau đó họ có thể bị xóa.
ravery

Câu trả lời:


35

Một cách đơn giản sẽ là loại bỏ các tệp này bằng inode của chúng. :)

Sử dụng ls -litrong thư mục với các ký tự không phổ biến để hiển thị số inode của mỗi tệp, ví dụ:

$ ls -li
total 0
133370 -rw-r--r-- 1 malte malte 0 Dec 30 19:00 ?2?.???љ?!?Gb??σ?[?F?
132584 -rw-r--r-- 1 malte malte 0 Dec 30 18:59 ??3]d???:????????1????G?p?ȋ??????嫳?d????ą-??

Tiếp theo, sử dụng findtiện ích để xóa tệp tương ứng theo tên của nó, sử dụng cú pháp find <somepath> -inum <inode_number> -exec rm -i {} \;, như trong ví dụ sau:

$ find . -inum 133370 -exec rm -i {} \;
rm: remove regular empty file ‘./?2?.???љ?!?Gb??σ?[?F?’? y
$ ls -li
total 0
132584 -rw-r--r-- 1 malte malte 0 Dec 30 18:59 ??3]d???:????????1????G?p?ȋ??????嫳?d????ą-??

Các -itùy chọn để rmkhông phải là thực sự cần thiết, tôi chỉ cần thêm nó để giữ cho bạn từ việc vô ý xóa các tập tin bạn không có nghĩa là để loại bỏ. :) Nó gây ra rmyêu cầu xác nhận cho mỗi tệp mà bạn muốn xóa.

Nếu bạn muốn xóa nhiều tệp bằng các nút của chúng, bạn có thể sử dụng cú pháp -o(có nghĩa hoặc ) cho find:

$ find .  \( -inum 133370 -o -inum 132584 \) -exec rm -i {} \;
rm: remove regular empty file ‘./?2?.???љ?!?Gb??σ?[?F?’? y
rm: remove regular empty file ‘./??3]d???:????????1????G?p?ȋ??????嫳?d????ą-??’? y

Bạn có thể thêm nhiều số inode hơn bằng cách mở rộng biểu thức trong ngoặc đơn với nhiều -o -inum <inode_number>biểu thức hơn .


4
Thế còn rm -ri .?
Brent Baccala

Điều này đã làm việc: tìm <somepath> -inum <inode_number> -exec rm -i {} \; '-Inum', '{}' và '\' làm gì trong lệnh?
karjedavpalaa

Làm cách nào để xóa nhiều tệp cùng một lúc? Ngoài ra, cảm ơn bạn, bạn đã làm cho ngày của tôi!
karjedavpalaa

2
@BrentBaccala rm -ri .không xóa các tệp bằng inode. Nó chỉ đơn giản sẽ lặp lại qua toàn bộ thư mục làm việc và yêu cầu từng tệp nếu bạn muốn xóa nó - và bạn phải rất chú ý những tệp nào nó yêu cầu để không vô tình xóa những tệp không mong muốn. Tôi chắc chắn sẽ không muốn sử dụng lệnh này cho thư mục chính của mình - nó chứa rất nhiều tệp. ;)
Malte Skoruppa

3
@karjedavpalaa (1) -inumbảo findtìm các tệp theo số inode của chúng. (2) {}khớp với (các) tệp được tìm thấy bởi grep. (3) \ thoát ;biểu tượng chấm dứt lệnh được truyền cho -exectùy chọn find. (4) Tôi đã chỉnh sửa câu trả lời của mình để giải thích cách xóa nhiều tệp trong một lần.
Malte Skoruppa

13

Điều quan trọng là phải hiểu rằng đây không phải là loại "tham nhũng hệ thống tập tin" fscksẽ giúp với. Theo như hệ thống tập tin, tên tệp có thể là bất kỳ chuỗi byte nào , miễn là không có byte nào có giá trị 0x00 (ASCII NUL, điểm đánh dấu kết thúc chuỗi C) hoặc 0x2F ( /, dấu phân cách thư mục). (Nếu một tên tệp bằng cách nào đó có được một byte 00 hoặc 2F được nhúng bên trong nó, fsckthì nên sửa nó.)

Thay vào đó, những gì bạn có là tên tệp mà phần mềm ứng dụng (Cá heo ls) nghĩ rằng có chứa các ký tự không thể hiển thị trong "ngôn ngữ" của bạn, do đó, nó sẽ thay thế chúng bằng các ký tự giữ chỗ. Bạn cũng không thể nhập các ký tự đó, do đó thao tác với các tệp khó hơn, nhưng bạn có thể làm điều đó miễn là bạn làm mà không cần phải gõ hoặc sao chép và dán tên. Ví dụ: nếu bạn xóa hoặc đổi tên các tệp vấn đề trực tiếp từ bên trong Cá heo, thì nó sẽ hoạt động (Tôi sẽ nói rằng nếu nó không hoạt động, đó là một lỗi trong Cá heo).

Nếu bạn cần làm gì đó với chúng từ shell (ví dụ: nếu chúng được sở hữu bởi rootvà do đó không thể được sửa đổi bởi chương trình GUI), bạn có thể đặt tên chúng một cách gián tiếp bằng cách sử dụng các mẫu "global", sẽ được mở rộng theo đúng trình tự (s) byte và được truyền cùng.

Tất nhiên, bây giờ, bạn sẽ không muốn xóa nội dung một cách tình cờ vì mẫu hình cầu của bạn khớp quá nhiều, vì vậy khuyến nghị của tôi là sử dụng renametiện ích Perl để chuyển đổi từng tên tệp thành mã hóa hex:

$ rename '$_ = unpack("H*", $_)' *

Điều này không phá hủy bất kỳ thông tin nào - không phải chính tệp đó, cũng không có nghĩa gì ban đầu được mã hóa trong tên tệp trước khi bị xáo trộn. Nó có thể được hoàn tác cho các tập tin cụ thể với ví dụ

$ rename '$_ = pack("H*", $_)' 696d706f7274616e742e646f63

Chú ý: có hai chương trình được đặt tên rename, từ các nguồn gốc khác nhau; các lệnh trên sẽ chỉ hoạt động với lệnh khởi tạo với Perl. Trong Ubuntu, cái bạn muốn là cái từ gói "đổi tên", không phải cái từ gói "produc-linux". rename -hsẽ phân biệt: đây là những gì bạn muốn ...

$ rename -h
Usage:
    rename [ -h|-m|-V ] [ -v ] [ -n ] [ -f ] [ -e|-E perlexpr]*|perlexpr
    [ files ]
# ...

... đây không phải điều bạn muốn ...

$ rename -h

Usage:
 rename [options] <expression> <replacement> <file>...
# ...

Điều quan trọng để tìm kiếm là "perlexpr". Bạn có thể có một phiên bản cũ hơn của việc đổi tên Perl mà không hiểu tất cả các tùy chọn ở trên, nhưng lệnh tôi đã hiển thị vẫn hoạt động.

Chỉnh sửa: Dưới 14.04 .5 tập lệnh perl được bao gồm renamekhông hỗ trợ chuyển đổi -h. Bạn có thể xác nhận bạn có đúng trang bằng cách kiểm tra trang man của nó man renametrong trường hợp nào dòng trên cùng sẽ chứa:

RENAME (1) Hướng dẫn tham khảo cho lập trình viên Perl RENAME (1)


đổi tên --version Tùy chọn không xác định: phiên bản
Elder Geek

@ElderGeek file $(which rename)In gì? (Hãy chắc chắn rằng bạn đã filecài đặt gói đầu tiên.)
zwol

/usr/bin/rename: symbolic link to /etc/alternatives/rename( fileđược cài đặt theo mặc định) Trên thực tế, bạn phải truy tìm các liên kết tượng trưng để nhận /usr/bin/file-rename: a /usr/bin/perl -w script, ASCII text executable nhưng man renamelà một dấu hiệu nhanh hơn ...
Elder Geek

@ElderGeek Nếu đó là tập lệnh perl, thì có lẽ đó là phiên bản cũ hơn của "tập lệnh có nguồn gốc từ Perl", điều đó không hỗ trợ --version; Lệnh tôi đề nghị vẫn nên hoạt động. (/usr/share/doc/rename/changelog.gz trên máy tính của tôi, chạy Debian không ổn định, chỉ ra rằng --versionđã được thêm vào trong phiên bản 0.10 của đổi tên Perl, vào năm 2013. Tôi ngạc nhiên khi Ubuntu vẫn vận chuyển một thứ gì đó cũ hơn thế, nhưng chương trình này đã không thực sự thay đổi chức năng của nó kể từ năm 2007 (!) nên nó vẫn ổn.)
zwol

Ah! Điều đó giải thích sự nhầm lẫn. Mặc dù có nhiều tuyên bố ngược lại, Debian không phải là Ubuntu. Tôi không thể nói cho mỗi bản phát hành, nhưng một số phiên bản hiện đang được hỗ trợ của Ubuntu LTS (14.04) vẫn không có điều đó. (Mặc dù 16.04 không)
Elder Geek
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.