Невозможно удалить / переместить файлы со специальными символами в имени файла

17

Как вы можете видеть ниже, файлы имеют необычные символы.

скриншот файлового менеджера

Удаление их либо в терминале, либо в Dolphin возвращает ошибку:

Данный файл или каталог отсутствует

Запуск ls -laв каталоге дал мне такой вывод:

-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

Я побежал fsck выполнил команду на разделе из другой ОС, но это ничего не изменило.

Как мне удалить эти файлы?

karjedavpalaa
источник
1
Вы настроили свою систему, чтобы иметь зашифрованный домашний каталог?
Добе
@ Я не знаю.
karjedavpalaa
5
@Panther Вы ошибаетесь. Это не сам по себе, свидетельствует о коррумпированной файловой системе, и даже если она была вызвана повреждением данных некоторого вида, Fsck не сделать ничего о нем.
Звол
1
У меня были файлы с неизвестными именами в имени. Переименование файлов сработало. тогда они могут быть удалены.
Ревери

Ответы:

35

Простой способ - удалить эти файлы по их индоду. :)

Используйте ls -liв каталоге с необычными символами, чтобы показать номер индекса каждого файла, например,

$ 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????ą-??

Затем с помощью findутилиты удалите соответствующий файл по его имени, используя синтаксис find <somepath> -inum <inode_number> -exec rm -i {} \;, как в следующем примере:

$ 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????ą-??

Эта -iопция rmне является действительно необходимой, я просто добавил ее, чтобы предотвратить случайное удаление файлов, которые вы не хотели удалять. :) Это вызываетrm запрос подтверждения для каждого файла, который вы хотите удалить.

Если вы хотите удалить несколько файлов по их inode, вы можете использовать синтаксис -o(значение или ) для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

Вы можете добавить больше номеров индексов, расширив выражение в скобках большим количеством -o -inum <inode_number>выражений.

Malte Skoruppa
источник
4
Как насчет rm -ri .?
Брент Баккала
Это сработало: find <somepath> -inum <inode_number> -exec rm -i {} \; Что '-inum', '{}' и '\' делают в команде?
karjedavpalaa
Как удалить несколько файлов за один раз? Также спасибо, ты сделал мой день!
karjedavpalaa
2
@BrentBaccala rm -ri .не удаляет файлы по inode. Он будет просто проходить по всему рабочему каталогу и запрашивать каждый файл, если вы хотите удалить его, и вы должны быть очень внимательны, какие файлы он запрашивает, чтобы случайно не удалить ненужные. Я, конечно, не хотел бы использовать эту команду для моего домашнего каталога - он содержит много файлов. ;)
Malte Skoruppa
3
@karjedavpalaa (1) -inumговорит findискать файлы по их номеру inode. (2) {}соответствует файлу (ам), найденному grep. (3) \ экранирует ;символ, который завершает команду, переданную -execопции find. (4) Я отредактировал свой ответ, чтобы объяснить, как удалить несколько файлов за один раз.
Malte Skoruppa
13

Важно понимать, что это не тот тип «повреждения файловой системы», fsckкоторый поможет с этим. Что касается файловой системы, то имена файлов могут быть любой последовательностью байтов , если ни один байт не имеет значения 0x00 (ASCII NUL, маркер конца строки C) или 0x2F ( /разделитель каталогов). (Если имя файла каким-либо образом вставляется в байт 00 или 2F,fsck следует исправить.)

Скорее, у вас есть имена файлов, которые, по lsмнению прикладного программного обеспечения (Dolphin ), содержат символы, которые невозможно отобразить в вашей «локали», поэтому он заменяет их символами-заполнителями. Вы также не можете вводить эти символы, так что манипулировать файлами сложнее, но вы можете делать это до тех пор, пока вы не наберете, не скопируете и не вставите имя. Например, если вы удаляете или переименовываете проблемные файлы непосредственно из Dolphin, это должно работать просто (я бы сказал, что если это не работает, это ошибка в Dolphin).

Если вам нужно что-то с ними сделать из оболочки (например, если они принадлежат rootи, следовательно, не могут быть изменены программой с графическим интерфейсом), вы можете указать их косвенно, используя шаблоны «glob», которые будут расширены до правильной последовательности. (s) байтов и переданы.

Теперь, конечно, вы не захотите удалить материал случайно, потому что ваш шаблон глобуса слишком сильно совпадает, поэтому я рекомендую использовать renameутилиту Perl для преобразования каждого имени файла в его шестнадцатеричную кодировку:

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

Это не уничтожает какую-либо информацию - ни сам файл, ни какое-либо значение, возможно, изначально были закодированы в имени файла до того, как оно было искажено. Это может быть отменено для определенных файлов, например,

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

Осторожно: есть две названные программы renameиз разных источников; вышеупомянутые команды будут работать только с той, которая возникла в Perl. В Ubuntu вам нужен тот, что из пакета «переименовать», а не тот, из пакета «util-linux». rename -hбудет отличать: это то, что вы хотите ...

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

... это не то, что вы хотите ...

$ rename -h

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

Ключевая вещь, чтобы искать это "Perlexpr". У вас может быть более старая версия переименования Perl, которая не понимает все перечисленные выше параметры, но команда, которую я показал, должна работать.

Изменить: до 14.04 .5 скрипт perl, который включен для rename, не поддерживает ключ -h. Вы можете подтвердить, что у вас есть правильный, проверив его справочную страницу, и man renameв этом случае верхняя строка будет содержать:

RENAME (1) Справочное руководство по программированию на Perl RENAME (1)

zwol
источник
переименовать --version Неизвестная опция: версия
Старейшина Гик
@ElderGeek Что file $(which rename)печатает? ( fileСначала убедитесь, что у вас установлен пакет.)
zwol
/usr/bin/rename: symbolic link to /etc/alternatives/rename( fileустановлено по умолчанию) На самом деле вам нужно искать символические ссылки, /usr/bin/file-rename: a /usr/bin/perl -w script, ASCII text executable но man renameэто более быстрое указание ...
Старейшина Гик
@ElderGeek Если это скрипт на perl, то, вероятно, это более старая версия «той, что написана на Perl», которая не поддерживает --version; Команда, которую я предложил, должна работать. (/usr/share/doc/rename/changelog.gz на моем компьютере, на котором работает нестабильная --versionверсия Debian, указывает, что он был добавлен в версию 0.10 переименования Perl в 2013 году. Я удивлен, что Ubuntu все еще выпускает нечто более старое, чем это, но эта программа фактически не изменила свою функциональность с 2007 года (!), так что все в порядке.)
zwol
Ах! Это объясняет путаницу. Несмотря на множество заявлений об обратном, Debian не является Ubuntu. Я не могу говорить о каждом выпуске, но некоторые поддерживаемые в настоящее время версии Ubuntu LTS (14.04) все еще не имеют этого. (Хотя 16.04 делает)
Старейшина Гик