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

15

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

Удаление их либо в терминале, либо в 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 [email protected],?Zp?[?bI????7^?ñ[?ڏ??z?O???ч??eEȰ?+??,OF??h

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

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

задан karjedavpalaa 30.12.2017 в 18:46
источник

2 ответа

33

Простым способом было бы удалить эти файлы с помощью своего inode. :)

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

$ 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 , чтобы запросить подтверждение для каждого файла, который вы хотите удалить.

Если вы хотите удалить несколько файлов с помощью своих inodes, вы можете использовать синтаксис -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

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

    
ответ дан Malte Skoruppa 30.12.2017 в 19:04
источник
13

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

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

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

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

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

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

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

Внимание: существуют две программы с именем rename , из разных источников; приведенные выше команды будут работать только с тем, что происходит с Perl. В Ubuntu, который вы хотите, это тот, который вы хотите получить от пакета «rename», а не из пакета «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-страницу с man rename , и в этом случае верхняя строка будет содержать:

  

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

    
ответ дан zwol 30.12.2017 в 23:56