Saturday, September 19, 2009

Nautilus и файлы MIME-типа application/octet-stream

В Gnome Desktop файловый менеджер Nautilus использует классификацию файлов в соответсвии с MIME-типами (Content-type) содержимого файлов. В частности это напрямую используется для задания программ используемых по-умолчанию для открытия файлов по двойному клику на имени файла или из контекстного меню 'Open with'.

В настройках Nautilus для отображения папок в режиме 'View as List' я всегда заменяю колонку 'Type' на 'MIME Type'.

Можно заметить что умная программа пытается распознать тип файла при обращении к нему именно по содержанию файла, а не по его расширению. Иногда это приводит к ошибке, например файл /etc/yum.conf распознаётся как application/x-cisco-vpn-settings.

Нераспознанные по содержимому файлы определяются MIME-типом, который соответствует произвольным двоичным данным - application/octet-stream. При попытке открыть такие файлы по двойному клику Nautilus просто и незатейливо выдаёт окошко:
Couldn't display "имя_файла".

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

Но это как бы не должно быть сильно неудобно, ведь в любом случае для файла можно задать приложение или команду для его открытия через пункт контекстного меню 'Open with Other Application...'. В этом случае в соответствии с расширением, которое имеет имя файла в системе регистрируется новый MIME-тип 'application/x-extension-расширение_файла', и все файлы попадающие под соответсвующий glob pattern считаются принадлежащими этому MIME-типу и открываются указанным приложением или командой.

Чтоб посмотреть нужный файл через 'Open with Other Application...' я обычно выбираю по ситуации либо gedit (пункт Text Editor), либо в строке 'Use a custom command' задаю команду 'gnome-terminal --geometry=127x41 -x less', т.к. через less в териминале если будет нужно потом можно выйти в vim и далее посмотреть/отредактировать файл в hex-формате с помощью xxd.

Пользовательская база данных созданных MIME-типов располагается в директории  ~/.local/share/mime,
основной конфигурационный файл  ~/.local/share/mime/packages/Override.xml
Подробнее об этом можно прочитать здесь:  http://www.freedesktop.org/wiki/Specifications/AddingMIMETutor
А регистрация связи между MIME-типом файла и приложением которое может его открывать происходит с помощью .desktop-файлов в директории  ~/.local/share/applications
Про .desktop-файлы на сайте freedesktop.org можно найти следующую ссылки:
http://www.freedesktop.org/wiki/Howto_desktop_files
http://standards.freedesktop.org/desktop-entry-spec/latest/

Наводкой на инфу на freedesktop.org о добавлении собственных MIME-типов послужило найденное описание некой похожей ситуации:
http://linux.seindal.dk/2004/07/01/nautilus-2-6-and-mime-types/

Однако приём с автоматическим добавлением нового MIME-типа через пункт контекстного меню 'Open with Other Application...' не рабоает если у имени файла нет расширения. При попытке воспользоваться им Nautilus выдаёт ошибку:
Could not add application
Could not add application to the application database


Обычно я этим не заморачивался, просто если нужно было иметь дело с такими файлами откравал консоль и смотрел/редактировал их через less/vim. Но в случае когда имеешь много файлов данных (например дампов) с похожими друг на друга длинными именами, которые неудобно открывать вручную через консоль из-за множества escape'ов и различающихся цифр в имени, это уже станвится не так здорово. Очевидно что превращать всякий раз файл типа application/octet-stream в некий другой MIME-тип создавая и регистрируя его в системе для каждого файла или группы файлов по glob pattern это не совсем то что нужно. Фактически всё что требуется это просто задать для Nautilus некую универсальную программу-просмоторщих любого файла любого имеющегося MIME-типа, ну или хотябы уж для файлов типа application/octet-stream. Сделать через меню Nautilus это нельзя. Можно попробовать вручную создать .desktop-файл для открытия файлов MIME-типа application/octet-stream. Программой просмоторщиком может служить тот-же less запущенный в gnome-terminal.

.desktop-файлы - это текстовые файлы с расширением '.desktop', содержащие нужные параметры настройки в виде переменных с присвоенными им значениями. В Gnome с ними происходит такая штука: в Nautilus они отображаются без расширения '.desktop' и не под тем именем под которвм лежат в файловой системе, а под именем определённым в самом файле. Эта странность определённым образом напоминает распространённую ситуацию со специальными папками и файлами в Windows Explorer, когда вместо фактического листинга директории или фактического файла на диске показывается некое содержимое папки или некий эелемент в соответствии с теми представлениями которые посчитали нужным создать разработчики GUI для этой директории или файла. Я надеялся не увидеть в Linux таких "концепций". Зачем разработчики Gnome переняли этот опыт не понятно (хотя судя по всему это сделано по-видимому для того, чтобы иметь возможность отображать название одного и того же .desktop-файла под разными именами, на языке соответствующем пользовательской локали). Да и вообще стоит сказать спасибо что это простой текстовый файл, а не xml-формат - редкое явление для конфигурационных файлов в Gnome Desktop. Наверное забыли переделать, а может просто не поддались всеобщей мании использовать xml-формат везде где ни попадя, не только как формат файлов для обмена информацией между компьютерами или программами, но и для самых простых конфигурационных файлов предназначенных исключительно для создания и редактирования человеком, заставляя его работать на подобие машины, набирая бессмсленную кучу ненужных тэгов и следить чтоб все они были корректно закрыты -- в общем создать неудобства для человека для удобства автоматической обработки файла. (Ну ладно, это конечно всё лирика.)

Для привязки в Nautilus нужной программы-просмоторщика к файлам MIME-типа application/octet-stream достаточно в директории  ~/.local/share/applications  создать файл с любым именем и расширением '.desktop' следующего содержания:
[Desktop Entry]
Version=1.0
Encoding=UTF-8
Name=mime octet-stream viewer
MimeType=application/octet-stream;
Exec=gnome-terminal --geometry=127x41 -x less %f
Type=Application
Terminal=false
NoDisplay=true
Затем проверить его на ошибки с помощью утилиты desktop-file-validate и выполнить команду обновления базы данных update-desktop-database для этой директории:
[mike@localhost ~]$ vim .local/share/applications/mime-octet-stream-viewer.desktop
[mike@localhost ~]$ desktop-file-validate .local/share/applications/mime-octet-stream-viewer.desktop 
[mike@localhost ~]$ update-desktop-database .local/share/applications
После этого в Nautilus в контекстном меню для файлов MIME-типа application/octet-stream пункт 'Open' будет называться 'Open with "mime octet-stream viewer"' и при двойном клике на имени файла будет запускаться в Gnome Terminal его просмотр с помощью утилиты less.

Friday, September 11, 2009

bash-scripting: три способа узнать содержится ли подстрока в строке

Если нужно узнать содержится ли в некой строке (пускай она хранится в переменной) некая подстрока (другая переменная), например, присутствует ли некий путь $DIR в переменной $PATH, то, есть как минимум три способа это сделать.

Способ 1:

echo "$PATH" | /bin/egrep -q "(^|:)$DIR($|:)"
TEST=$?


Или чуть проще:

/bin/egrep -q "(^|:)$DIR($|:)" <<< "$PATH"
TEST=$?


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

Способ 2 (наш антисимметричный ответ чемберлену):

[ "$PATH" = "$DIR" -o \
  "${PATH##$DIR:}" != "$PATH" -o \
  "${PATH%%:$DIR}" != "$PATH" -o \
  "${PATH/:$DIR:}" != "$PATH" ]
TEST=$?


Достоинства: "хм...".
Недостатки: "о, это чёэто ваще такое тут!?"
В общем достоинства этого способа противоположны недостаткам первого. С недостатками, как видно, аналогично.

Способ 3 (попытка примирения):

[[ "$PATH" == "$DIR" || "$PATH" == "$DIR":* || "$PATH" == *:"$DIR" || "$PATH" == *:"$DIR":* ]]
TEST=$?

Wednesday, September 2, 2009

Системная консоль

Системная консоль - консоль на которую посылаются сообщения ядра.

В Documentation/serial-console.txt, описывается настройка системной консоли на терминальное устройство, подключаемое через последовательный порт. Но ещё в этом документе раскрывается общий порядок выбора устройства, на котором будет производится ввод/вывод системной консоли. Вот цитата и перевод с комментариями из этого файла, касающийся порядка выбора этого устройства (вообще там дальше по тексту приводится полный пример как настроить консоль на последовательный порт, так что если такое вдруг понадобится, то следует обращаться к этому документу):

 --------------------- Documentation/serial-console.txt ----------------------
/                                                                             \

It is possible to specify multiple devices for console output. You can
define a new kernel command line option to select which device(s) to
use for console output.
Имеется возможность указывать несколько устройств для консольного вывода.
Вы можете задать параметр командной строки ядра чтобы выбрать какие
устройства использовать для консольного вывода.

The format of this option is:
Формат опции такой:

        console=device,options

        device:         tty0 for the foreground virtual console
                             для первого виртуального терминала (виртуальной
                             консоли)
                        ttyX for any other virtual console
                             для остальных виртуальных терминалов (консолей)
                        ttySx for a serial port
                              для последовательного порта
                        lp0 for the first parallel port
                            для первого параллельного порта
                        ttyUSB0 for the first USB serial device
                                для первого USB устройства

        options:        depend on the driver. For the serial port this
                        defines the baudrate/parity/bits/flow control of
                        the port, in the format BBBBPNF, where BBBB is the
                        speed, P is parity (n/o/e), N is number of bits,
                        and F is flow control ('r' for RTS). Default is
                        9600n8. The maximum baudrate is 115200.
                        опции зависят от драйвера устройства.
                        Для последовательного порта здесь определяются опции
                        для скорости соединения/чётности/разрядности/режима
                        управления портом в формате BBBBPNF где BBBB это
                        скорость, P режим контроля чётности (n/o/e),
                        N - количество разрядов, и F - режим управления
                        потоком ('r' для RTS). По-умолчанию значение '9600n8'.
                        Максимальная скорость 115200. 

You can specify multiple console= options on the kernel command line.
Output will appear on all of them. The last device will be used when
you open /dev/console. So, for example:
Вы можете указать опцию 'console=' несколько раз в командной строке ядра.
Вывод появится на всех этих устройствах. Последнее из указанных устройств будет
использоваться как устройство /dev/console. Так например:

        console=ttyS1,9600 console=tty0

defines that opening /dev/console will get you the current foreground
virtual console, and kernel messages will appear on both the VGA
console and the 2nd serial port (ttyS1 or COM2) at 9600 baud.
определяет что устройство /dev/console будет связано с текущим виртуальным
терминалом, и сообщения ядра будут появляться одновременно как на VGA консоли
так и на втором последовательном порте (ttyS1 или COM2) на скорости 9600 бод.

Note that you can only define one console per device type (serial, video).
Следует заметить что вы можете определить только по одной системной консоли
на каждый тип устройства (последовательный порт, видеоустройство).

If no console device is specified, the first device found capable of
acting as a system console will be used. At this time, the system
first looks for a VGA card and then for a serial port. So if you don't
have a VGA card in your system the first serial port will automatically
become the console.
Если не указано никакого устройства для консоли (как это обычно и бывает),
то будет использовано первое найденное устройство способное работать в качестве
системной консоли. В настоящее время система сначала просматривает устройства
VGA видеокарт и потом последовательный порт. Так что если у вас нет в системе
VGA видеокарты, то первый последовательный порт автоматически станет системной
консолью.

You will need to create a new device to use /dev/console. The official
/dev/console is now character device 5,1.
Вам будет нужно создать новое устройство для того чтобы использовать
/dev/console. /dev/console является символьным устройством с номером 5,1.

(You can also use a network device as a console.  See
Documentation/networking/netconsole.txt for information on that.)
(Вы также можете использовать стевую карту в качестве системной консоли.
См. информацию в Documentation/networking/netconsole.txt по этому поводу.)

\                                                                             /
 --------------------- Documentation/serial-console.txt ----------------------