Все ленты — последние статьи

Работа с «плохими» файлами в командной строке в Linux

При работе в командной строке администраторы часто сталкиваются с необходимостью что-то сделать с определенным файлом: удалить, переместить, скопировать. При выполнении подобных задач зачастую приходится обращаться к файлам по имени, что может быть затруднительно, поскольку в именах файлов могут встречаться самые разные символы. Даже те, которых нет на клавиатуре. В этом плане работу может облегчить файловый менеджер, в котором файл можно просто выделить и совершить с ним нужное действие. Но для тех, кто привык работать исключительно в командной строке, предлагаются следующие способы.

 

В качестве shell-оболочки рассмотрим bash, как самую используемую. А в качестве операции над файлами рассмотрим удаление, как самую деструктивную.

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


В названии файла есть служебный символ bash

Самый простой случай. Для удаления файлов, содержащих в своем названии служебные символы вроде пробелов, кавычек, двойных кавычек, звездочек, обратные кавычки и др. можно заэкранировать обратным слешем или использовать одинарные кавычки:

$ rm -f my:file name
$ rm -f 'my file with white:spaces:and:colons'
$ rm -f (filename)


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

С полным списком служебных символов и механизмом экранирования в bash можно ознакомиться в man bash. Раздел QUOTING.


Имя файла начинается с дефиса

Удалить файл, начинающийся с дефиса простым экранированием не получится, и команда rm будет воспринимать дефис, как начало своего аргумента. Решить проблему довольно просто:

$ rm -f ./-abc


или:

$ rm -f -- -abc

Удаляем по wildcard

Если удаление файлов попадает под wildcard-маску, то можно удалить всю группу файлов:

$ rm -f *.jpg

Файлы с управляющим символом в названии

В названии файла может встречаться управляющий ASCII-символ, такой как перевод строки (n), табуляция (t), backspace (b). Это символы с ASCII-кодами менее 0x20, а также символы DELETE и ESC. Для удаления таких файлов подходит конструкция:

$ rm -f $'anynfile'
$ rm -f $'anybfile'


Другим способом удаления таких файлов являяется ввод управляющего символа с клавиатуры. Для этого нужно воспользоваться комбинацией клавиш, которая экранирует следующий введенный символ, тем самым запрещая системе обрабатывать его. Как правило, эта комбинация CTRL+V. Точно убедиться в этом можно с помощью команды stty -a, посмотрев на параметр lnext. Удалим файл, содержащий символ ESC:

$ rm -f any # жмем CTRL+V, затем ESC
$ rm -f any^[ # дописываем отсальные символы
$ rm -f any^[file

Удаление файлов с символами utf8

Если имя файла содержит символ в кодировке utf8, который мы не можем набрать на клавиатуре, то удалить такой файл можно выделением его мышкой, копированием в буфер обмена и последующей вставкой на ввод команды rm. Главное условие состоит в том, что наш терминал должен работать в кодировке utf8. Кодировка выставляется в настройках терминала. Будь то xterm, putty или брутальный linux tty.

$ ls -1
朲晦
朲晩
朲晪
$ rm -f 朲晪

Перекодировка имени файла

Подозревая, что имя файла находится в кодировке, отличной от кодировки терминала, мы можем выполнить перекодирование всех файлов в текущей директории. В результате файлы с битой кодировкой будут перекодированы, а файлы с ascii-символами изменений не претерпят. Существенный плюс этого способа — приведение всех файлов в читабельный вид.

$ convmv -fcp1251 -tutf8 *


Как видно, чтобы осуществить правильное перекодирование нужно знать две кодировки: предполагаемую кодировку файла и кодировку нашего терминала. Наиболее трудно распознать предполагаемую кодировку файла по непонятным символам. Есть замечательная табличка

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

Если вы встретили такие символы в примонтированном media-носителе или смонтированном разделе Windows, не спешите ничего перекодировать. Возможно, вы просто указали неправильные опции монтирования.

Автокомплит

В случае, если в директории название требуемого файла начинается уникально, и это название можно однозначно сформировать автокомплитом, то это довольно простой способ удалить файл:

$ rm -f icantype_ # жмем TAB
$ rm -f icantype_�� ������.jpg

Удаляем файл через меню выбора

Если мы дошли сюда, дело плохо. Попробуем удалить конкретный файл, составив для этого меню выбора. В итоге, все что нам останется сделать — это выбрать нужный пункт меню вместо ввода имени файла. Для этого нам нужно запрограммировать действие, которое будет происходить с файлом или файлами после ввода нами нужных пунктов меню.

$ select i in *; do rm -f $i; done
1) file.zip 3) ??? ???.doc 5) 朲晩
2) ?? ??.jpg 4) 朲晦
#? 2
#? ^C

Удаление по номеру inode

Удалить файл можно по его номеру inode. Номер inode уникально идентифицирует файл в файловой системе. Узнать номер inode можно с помощью команды ls, а удалить — с помощью find. Недостаток этого способа, такой же, как у предыдущего. Неудобно, в случае большого числа файлов.

$ ls -1 -i
144368 ???.txt
144363 ??.txt
$ find . -inum 144368 -delete

Удаление по hex-коду

И нельзя не упомянуть один суровый метод. Удаление по hex-кодам. Суть такова: мы узнаем hex-коды всех байтов в имени файла, а затем удаляем файл, указывая вместо имени hex-коды.

$ for i in *; do echo -n $i xxd ; done
0000000: face c0d0 32a4 ....2.
$ rm -f $'xfaxcexc0xd0x32xa4'


Хорошо, все-таки, что на практике такие файлы попадаются нечасто.