<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;DEUCQHg4eyp7ImA9WhRRFE4.&quot;"><id>tag:blogger.com,1999:blog-4154333943174084921</id><updated>2011-11-28T01:24:21.633+02:00</updated><category term="linux" /><category term="C++" /><category term="scheme" /><category term="математика" /><category term="консоль" /><category term="jabber" /><category term="python" /><category term="Programming Praxis" /><category term="сеть" /><category term="утилиты" /><category term="регулярные выражения" /><category term="звук" /><category term="программирование" /><category term="GNOME" /><title>Всё чудесатее и чудесатее</title><subtitle type="html">Блог о разных интересностях, чаще компьютерных, но не без исключений</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://strange-to-say.blogspot.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://strange-to-say.blogspot.com/" /><author><name>Вадим</name><uri>http://www.blogger.com/profile/03928284652612977325</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="30" height="32" src="http://1.bp.blogspot.com/_hRyhd7EUrGc/Sk5VleynHlI/AAAAAAAAAfE/ucW5wDwhBPw/S220/my_avatar.gif" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>15</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/blogspot/zKMV" /><feedburner:info uri="blogspot/zkmv" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry gd:etag="W/&quot;A0QMQHY6fSp7ImA9WxFVFU8.&quot;"><id>tag:blogger.com,1999:blog-4154333943174084921.post-229757851018959860</id><published>2010-06-14T17:30:00.005+03:00</published><updated>2010-06-14T18:29:41.815+03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-06-14T18:29:41.815+03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="звук" /><category scheme="http://www.blogger.com/atom/ns#" term="linux" /><category scheme="http://www.blogger.com/atom/ns#" term="утилиты" /><title>И снова о разрезании lossless-аудио (ape, flac, wv, wav) по файлу cue</title><content type="html">&lt;a href="http://strange-to-say.blogspot.com/2009/10/lossless-ape-flac-wv-wav-cue.html"&gt;Ранее&lt;/a&gt; я выкладывал перевод одной заметки о том, как разрезать lossless-аудио на отдельные треки. Однако, в комментариях мне подсказали более простой способ.&lt;br /&gt;&lt;br /&gt;&lt;span class="fullpost"&gt;&lt;br /&gt;Для этого понадибится утилита shntool (в Debian и Ubuntu живёт в одноимённом пакете). Вообще, это настоящий швейцарский армейский нож в области работы со звуковыми файлами (в том числе и сжатыми), в чём можно убедиться, открыв соответствующий man:&lt;br /&gt;&lt;pre&gt;man shntool&lt;/pre&gt;Вот перечень некоторых команд, которые эта утилита поддерживает:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;len — отображает продолжительность, размер и свойства звуковых данных&lt;/li&gt;&lt;li&gt; join — объединяет несколько файлов в один&lt;/li&gt;&lt;li&gt;split — разбивает звуковой файл на несколько отдельных файлов&lt;/li&gt;&lt;li&gt;cue — генерирует файл CUE или список точек разбиения по набору файлов&lt;/li&gt;&lt;li&gt;conv — преобразует из одного формата в другой&lt;/li&gt;&lt;li&gt;trim — удаляет тишину по краям записи&lt;/li&gt;&lt;/ul&gt;Список поддерживаемых форматов тоже немал: wav (RIFF WAVE), aiff (Audio Interchange File Format), shn (Shorten low complexity waveform coder), flac (Free Lossless Audio Codec), ape (Monkey's Audio Compressor), ofr (OptimFROG Lossless WAVE), lpac (Lossless Predictive Audio Compression), wv (WavPack Hybrid Lossless Audio Compression), alac (Apple Lossless Audio Codec) и другие, менее распространённые.&lt;br /&gt;&lt;br /&gt;Естественно, для поддержки форматов нужно доустанавливать соответствующие утилиты. Для flac, ape и wv:&lt;br /&gt;&lt;pre&gt;sudo apt-get install flac wavpack monkeys-audio&lt;/pre&gt;Собственно команда для разрезания будет иметь вид:&lt;br /&gt;Эта команда не только разобьёт исходный flac-файл, но и переименует каждый трек в соответствии с форматом:&lt;br /&gt;&lt;br /&gt;Исполнитель (Альбом) - Номер - Название&lt;br /&gt;&lt;br /&gt;Естественно, можно указать и другой формат, задав свою строку и используя постановочные символы %p, %a, %n, %t.&lt;br /&gt;&lt;br /&gt;Если файлы Music.flac и Music.cue расположены в одной папке, имеют одинаковое имя, как в данном случае и других подобных файлов нет, то можно использовать следующий скрипт:&lt;br /&gt;&lt;pre   style="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255);font-family:'Courier New';font-size:10pt;"&gt;&lt;span style="color: rgb(131, 129, 131); font-style: italic;"&gt;#!/bin/bash&lt;/span&gt;&lt;br /&gt;f&lt;span style="color: rgb(0, 0, 0);"&gt;=&lt;/span&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;`ls *.cue`&lt;/span&gt;&lt;br /&gt;f&lt;span style="color: rgb(0, 0, 0);"&gt;=&lt;/span&gt;&lt;span style="color: rgb(1, 1, 129);"&gt;${f%.cue}&lt;/span&gt;&lt;br /&gt;shntool &lt;span style="color: rgb(0, 0, 0); font-weight: bold;"&gt;split&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0);"&gt;-&lt;/span&gt;f &lt;span style="color: rgb(255, 0, 0);"&gt;"$f.cue"&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0);"&gt;-&lt;/span&gt;o flac &lt;span style="color: rgb(255, 0, 0);"&gt;"$f.flac"&lt;/span&gt; &lt;span style="color: rgb(0, 0, 0);"&gt;-&lt;/span&gt;t &lt;span style="color: rgb(255, 0, 0);"&gt;"%p (%a) - %n - %t"&lt;/span&gt;&lt;/pre&gt;Я его назвал split_flac и поместил в ~/bin. Чтобы им воспользоваться достаточно зайти в директорию с разрезаемыми файлами и выполнить всего одну команду:&lt;br /&gt;&lt;pre&gt;split_flac&lt;/pre&gt;Аналогичный скрипт можно написать и для формата APE. А можно сделать один большой интеллектуальный скрипт, если не лень.&lt;br /&gt;&lt;br /&gt;Чтобы не было закорючек в именах, нужно следить, чтобы файл cue был в той же кодировке, что и текущая локаль (обычно, UTF-8).&lt;br /&gt;&lt;br /&gt;Единственный минус — теги будут пустыми, но их можно заполнить командой cuetag или какой-то специализированной утилитой наподобие EasyTAG.&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4154333943174084921-229757851018959860?l=strange-to-say.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/jutphMOnkdBMj3Bh57-shpWSt00/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/jutphMOnkdBMj3Bh57-shpWSt00/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/jutphMOnkdBMj3Bh57-shpWSt00/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/jutphMOnkdBMj3Bh57-shpWSt00/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/zKMV/~4/Kz8dW_dEwQg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://strange-to-say.blogspot.com/feeds/229757851018959860/comments/default" title="Комментарии к сообщению" /><link rel="replies" type="text/html" href="http://strange-to-say.blogspot.com/2010/06/lossless-ape-flac-wv-wav-cue.html#comment-form" title="Комментарии: 0" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4154333943174084921/posts/default/229757851018959860?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4154333943174084921/posts/default/229757851018959860?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/zKMV/~3/Kz8dW_dEwQg/lossless-ape-flac-wv-wav-cue.html" title="И снова о разрезании lossless-аудио (ape, flac, wv, wav) по файлу cue" /><author><name>Вадим</name><uri>http://www.blogger.com/profile/03928284652612977325</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="30" height="32" src="http://1.bp.blogspot.com/_hRyhd7EUrGc/Sk5VleynHlI/AAAAAAAAAfE/ucW5wDwhBPw/S220/my_avatar.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://strange-to-say.blogspot.com/2010/06/lossless-ape-flac-wv-wav-cue.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUAEQXo8fSp7ImA9WxFVEEU.&quot;"><id>tag:blogger.com,1999:blog-4154333943174084921.post-3044499393359486348</id><published>2010-06-08T21:05:00.005+03:00</published><updated>2010-06-09T15:48:20.475+03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-06-09T15:48:20.475+03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Programming Praxis" /><category scheme="http://www.blogger.com/atom/ns#" term="python" /><category scheme="http://www.blogger.com/atom/ns#" term="scheme" /><title>Решето Эратосфена / Sieve of Eratosthenes</title><content type="html">&lt;a href="http://programmingpraxis.com/2009/02/19/sieve-of-eratosthenes/"&gt;Programming Praxis, 19.02.2009&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Более двух тысяч лет назад Эратосфен, который вычислил окружность Земли, расстояние до Солнца и наклон земной оси, изобрёл широту и долготу, а также придумал високосный день, создал систематический метод перечисления всех простых числе, который используется и по сей день.&lt;br /&gt;Эратосфен родился в Кирене (на территории современной Ливии) и жил с 276 г. до н. э. по 194 до н. э. Он провёл большую часть своей жизни в Александрии (Египет), где был вторым главой Великой библиотеки перед &lt;a href="http://ru.wikipedia.org/wiki/%D0%90%D0%BF%D0%BE%D0%BB%D0%BB%D0%BE%D0%BD%D0%B8%D0%B9_%D0%A0%D0%BE%D0%B4%D0%BE%D1%81%D1%81%D0%BA%D0%B8%D0%B9"&gt;Аполлонием Родосским&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Решето Эратосфена начинается с создания списка натуральных чисел до желаемого предела; проиллюстрируем метод, вычислив простые числа до тридцати:&lt;br /&gt;&lt;br /&gt;2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30&lt;br /&gt;&lt;br /&gt;Теперь возьмём первое число в списке — 2 — и вычеркнем каждое второе число:&lt;br /&gt;&lt;br /&gt;2 3 &lt;span style="text-decoration: line-through;"&gt;4&lt;/span&gt; 5 &lt;span style="text-decoration: line-through;"&gt;6&lt;/span&gt; 7 &lt;span style="text-decoration: line-through;"&gt;8&lt;/span&gt; 9 &lt;span style="text-decoration: line-through;"&gt;10&lt;/span&gt; 11 &lt;span style="text-decoration: line-through;"&gt;12&lt;/span&gt; 13 &lt;span style="text-decoration: line-through;"&gt;14&lt;/span&gt; 15 &lt;span style="text-decoration: line-through;"&gt;16&lt;/span&gt; 17 &lt;span style="text-decoration: line-through;"&gt;18&lt;/span&gt; 19 &lt;span style="text-decoration: line-through;"&gt;20&lt;/span&gt; 21 &lt;span style="text-decoration: line-through;"&gt;22&lt;/span&gt; 23 &lt;span style="text-decoration: line-through;"&gt;24&lt;/span&gt; 25 &lt;span style="text-decoration: line-through;"&gt;26&lt;/span&gt; 27 &lt;span style="text-decoration: line-through;"&gt;28&lt;/span&gt; 29 &lt;span style="text-decoration: line-through;"&gt;30&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Затем берём следующее невычеркнутое число в списке — 3 — и вычёркиваем каждое третье число; некоторые из них окажутся уже вычеркнутыми:&lt;br /&gt;&lt;br /&gt;2 3 &lt;span style="text-decoration: line-through;"&gt;4&lt;/span&gt; 5 &lt;span style="text-decoration: line-through;"&gt;6&lt;/span&gt; 7 &lt;span style="text-decoration: line-through;"&gt;8&lt;/span&gt; &lt;span style="text-decoration: line-through;"&gt;9&lt;/span&gt; &lt;span style="text-decoration: line-through;"&gt;10&lt;/span&gt; 11 &lt;span style="text-decoration: line-through;"&gt;12&lt;/span&gt; 13 &lt;span style="text-decoration: line-through;"&gt;14&lt;/span&gt; &lt;span style="text-decoration: line-through;"&gt;15&lt;/span&gt; &lt;span style="text-decoration: line-through;"&gt;16&lt;/span&gt; 17 &lt;span style="text-decoration: line-through;"&gt;18&lt;/span&gt; 19 &lt;span style="text-decoration: line-through;"&gt;20&lt;/span&gt; &lt;span style="text-decoration: line-through;"&gt;21&lt;/span&gt; &lt;span style="text-decoration: line-through;"&gt;22&lt;/span&gt; 23 &lt;span style="text-decoration: line-through;"&gt;24&lt;/span&gt; 25 &lt;span style="text-decoration: line-through;"&gt;26&lt;/span&gt; &lt;span style="text-decoration: line-through;"&gt;27&lt;/span&gt; &lt;span style="text-decoration: line-through;"&gt;28&lt;/span&gt; 29 &lt;span style="text-decoration: line-through;"&gt;30&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;повторяем последний шаг для следующего невычеркнутого числа — 5:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;2 3 &lt;span style="text-decoration: line-through;"&gt;4&lt;/span&gt; 5 &lt;span style="text-decoration: line-through;"&gt;6&lt;/span&gt; 7 &lt;span style="text-decoration: line-through;"&gt;8&lt;/span&gt; &lt;span style="text-decoration: line-through;"&gt;9&lt;/span&gt; &lt;span style="text-decoration: line-through;"&gt;10&lt;/span&gt; 11 &lt;span style="text-decoration: line-through;"&gt;12&lt;/span&gt; 13 &lt;span style="text-decoration: line-through;"&gt;14&lt;/span&gt; &lt;span style="text-decoration: line-through;"&gt;15&lt;/span&gt; &lt;span style="text-decoration: line-through;"&gt;16&lt;/span&gt; 17 &lt;span style="text-decoration: line-through;"&gt;18&lt;/span&gt; 19 &lt;span style="text-decoration: line-through;"&gt;20&lt;/span&gt; &lt;span style="text-decoration: line-through;"&gt;21&lt;/span&gt; &lt;span style="text-decoration: line-through;"&gt;22&lt;/span&gt; 23 &lt;span style="text-decoration: line-through;"&gt;24&lt;/span&gt; &lt;span style="text-decoration: line-through;"&gt;25&lt;/span&gt; &lt;span style="text-decoration: line-through;"&gt;26&lt;/span&gt; &lt;span style="text-decoration: line-through;"&gt;27&lt;/span&gt; &lt;span style="text-decoration: line-through;"&gt;28&lt;/span&gt; 29 &lt;span style="text-decoration: line-through;"&gt;30&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;И так далее, каждый раз вычёркивая все числа, кратные следующему невычеркнутому числу в списке. Все невычеркнутые числа к концу процедуры будут простыми:&lt;br /&gt;&lt;br /&gt;2 3 5 7 11 13 17 19 23 29&lt;br /&gt;&lt;br /&gt;Этот метод называется решетом, потому что он просеивает весь исходный диапазон чисел в поисках простых чисел.&lt;br /&gt;&lt;br /&gt;Решето допускает некоторые оптимизации.&lt;br /&gt;&lt;br /&gt;Во-первых, нужно рассматривать только нечётные числа, так как первый проход вычеркнет все чётные за исключением 2, которое можно рассматривать отдельно. &lt;br /&gt;&lt;br /&gt;Во-вторых, вычёркивание нужно начинать с квадрата числа, которое рассматривается в данный момент, так как все меньшие составные числа уже были вычеркнуты на предыдущих шагах; например, рассматривая 3, вычёркивание нужно начинать с 9, так как 6 было вычеркнуто, когда рассматривали 2.&lt;br /&gt;&lt;br /&gt;В третьих, процедура останавливается на квадратном корне из максимального числа, так как все простые числа, большие него уже будут вычеркнуты к этому моменту. Так, в рассмотренном выше примере не было необходимости проверять числа, большие либо равные 7, так как квадрат 7 больше 30 — наибольшего числа в списке.&lt;br /&gt;&lt;br /&gt;Напишите функцию, которая принимает один аргумент n и возвращает список простых чисел, меньших либо равных n используя оптимизированный алгоритм, описанный выше. Примените эту функцию к 15485863 и посчитайте количество полученных простых чисел. &lt;br /&gt;&lt;br /&gt;&lt;span class="fullpost"&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Решение.&lt;/span&gt;&lt;br /&gt;Jos Koot написал следующую версию решета Эратосфена:&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="scheme"&gt;&lt;br /&gt;(define (primes n)&lt;br /&gt;  (let* ((max-index (quotient (- n 3) 2))&lt;br /&gt;         (v (make-vector (+ 1 max-index) #t)))&lt;br /&gt;    (let loop ((i 0) (ps '(2)))&lt;br /&gt;      (let ((p (+ i i 3)) (startj (+ (* 2 i i) (* 6 i) 3)))&lt;br /&gt;        (cond ((&amp;gt;= (* p p) n)&lt;br /&gt;               (let loop ((j i) (ps ps))&lt;br /&gt;                  (cond ((&amp;gt; j max-index) (reverse ps))&lt;br /&gt;                        ((vector-ref v j)&lt;br /&gt;                          (loop (+ j 1) (cons (+ j j 3) ps)))&lt;br /&gt;                        (else (loop (+ j 1) ps)))))&lt;br /&gt;              ((vector-ref v i)&lt;br /&gt;                (let loop ((j startj))&lt;br /&gt;                  (if (&amp;lt;= j max-index)&lt;br /&gt;                      (begin (vector-set! v j #f)&lt;br /&gt;                             (loop (+ j p)))))&lt;br /&gt;                      (loop (+ 1 i) (cons p ps)))&lt;br /&gt;              (else (loop (+ 1 i) ps)))))))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Существует миллион простых числе, меньших, либо равных 15485863:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;gt; (length (primes 15485863))&lt;br /&gt;1000000&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Моё решение.&lt;/span&gt;&lt;br /&gt;&lt;pre name="code" class="python"&gt;&lt;br /&gt;from math import sqrt&lt;br /&gt;&lt;br /&gt;def sieve(n):&lt;br /&gt;    l = range(3,n+1,2)&lt;br /&gt;    i = 0&lt;br /&gt;    while 2*i+3 &lt;= sqrt(n):&lt;br /&gt;        k = l[i]&lt;br /&gt;        l[(k**2-3)/2:(n-1)/2:k] = [0] * ((n-k**2+1)/(2*k)+1)&lt;br /&gt;        i += 1&lt;br /&gt;        while l[i] == 0:&lt;br /&gt;            i += 1&lt;br /&gt;    return [2] + filter(lambda x: x != 0, l)&lt;br /&gt;&lt;br /&gt;print len(sieve(15485863))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Казалось бы, использование сечений — не самый оптимальный способ присвоить значение сразу многим элементам списка, но при замене страшной строчки «l[(k**2-3)/2:(n-1)/2:k] = [0] * ((n-k**2+1)/(2*k)+1)» на цикл программ стала завершать работу не за 3.172 с, а за 5,056 с.&lt;br /&gt;&lt;br /&gt;Всего же для просеивания 15485863 числе программе потребовалось 545 итераций. Из упомянутых трёх секунд только полторы уходило на собственно просеивание. Остальное время программа отфильтровывала вычеркнутые элементы.&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4154333943174084921-3044499393359486348?l=strange-to-say.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/NmHp9pQXJEaoPBBsdPq_goWCTTY/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/NmHp9pQXJEaoPBBsdPq_goWCTTY/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/NmHp9pQXJEaoPBBsdPq_goWCTTY/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/NmHp9pQXJEaoPBBsdPq_goWCTTY/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/zKMV/~4/Mrr9b1rOCLU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://strange-to-say.blogspot.com/feeds/3044499393359486348/comments/default" title="Комментарии к сообщению" /><link rel="replies" type="text/html" href="http://strange-to-say.blogspot.com/2010/06/sieve-of-eratosthenes.html#comment-form" title="Комментарии: 0" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4154333943174084921/posts/default/3044499393359486348?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4154333943174084921/posts/default/3044499393359486348?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/zKMV/~3/Mrr9b1rOCLU/sieve-of-eratosthenes.html" title="Решето Эратосфена / Sieve of Eratosthenes" /><author><name>Вадим</name><uri>http://www.blogger.com/profile/03928284652612977325</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="30" height="32" src="http://1.bp.blogspot.com/_hRyhd7EUrGc/Sk5VleynHlI/AAAAAAAAAfE/ucW5wDwhBPw/S220/my_avatar.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://strange-to-say.blogspot.com/2010/06/sieve-of-eratosthenes.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0cBQ38yfip7ImA9WxFVEEs.&quot;"><id>tag:blogger.com,1999:blog-4154333943174084921.post-8726720007189103968</id><published>2010-06-07T00:45:00.011+03:00</published><updated>2010-06-09T10:37:32.196+03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-06-09T10:37:32.196+03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Programming Praxis" /><category scheme="http://www.blogger.com/atom/ns#" term="python" /><category scheme="http://www.blogger.com/atom/ns#" term="scheme" /><title>Обратный польский калькулятор / RPN Calculator</title><content type="html">&lt;span style="font-style:italic;font-size:75%;"&gt;Дисклеймер. Хотелось бы поделиться с людьми, которые не особо знают английский, задачками с довольно интересного сайта &lt;a href="http://programmingpraxis.com/2009/02/19/rpn-calculator/"&gt;Programming Praxis&lt;/a&gt;. Готовых переводов задач я не нашёл, а потому буду потихоньку сам их тут выкладывать. Задачки простые, но для того, чтобы не терять навыки программирования — самое то.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://programmingpraxis.com/2009/02/19/rpn-calculator/"&gt;Programming Praxis, 19.02.2009&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Реализовать обратный польский калькулятор, принимающий выражения вида «19 2.14 + 4.5 2 4.3 / - *», которое обычно вычисляется как «(19 + 2.14) * (4.5 - 2 / 4.3)» и соответствует 85.2974. Программа должна читать выражение со стандартного входа и выводить вершину стека с символом конца строки в стандартный вывод. Программа должна сохранять состояние стека операндов между выражениями.&lt;br /&gt;&lt;br /&gt;&lt;span class="fullpost"&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Решение.&lt;/span&gt;&lt;br /&gt;Единственная сложность заключается в обработке новой строки, которая в Scheme трактуется как пробел. Функция (op token) преобразует знак, из символа, полученного со входа, в оператор, который может быть использован для вычислений. Формат первой строки программы специфичен для Chez Scheme, но большинство реализаций Scheme предоставляют что-то подобное.&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="lisp"&gt;&lt;br /&gt;#! /usr/bin/scheme –script&lt;br /&gt;(define (next)&lt;br /&gt;  (cond ((eof-object? (peek-char)) (exit))&lt;br /&gt;        ((char=? (peek-char) #\space) (read-char) (next))&lt;br /&gt;        ((char=? (peek-char) #\newline) (read-char) ‘nl)&lt;br /&gt;        (else (read))))&lt;br /&gt;&lt;br /&gt;(define (op token) (case token ((+) +) ((-) -) ((*) *) ((/) /)))&lt;br /&gt;&lt;br /&gt;(let rpn ((token (next)) (stack ‘()))&lt;br /&gt;  (cond ((eq? ‘nl token) (display (car stack)) (newline) (rpn (next) (cdr stack)))&lt;br /&gt;        ((number? token) (rpn (next) (cons token stack)))&lt;br /&gt;        (else (rpn (next) (cons ((op token) (cadr stack) (car stack)) (cddr stack))))))&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Моё решение.&lt;/span&gt;&lt;br /&gt;&lt;pre name="code" class="python"&gt;&lt;br /&gt;#!/usr/bin/env python&lt;br /&gt;#-*- coding:utf-8 -*-&lt;br /&gt;&lt;br /&gt;from sys import stdin, stdout&lt;br /&gt;&lt;br /&gt;def calc():&lt;br /&gt;    stack = []&lt;br /&gt;    result = None&lt;br /&gt;    while True:&lt;br /&gt;        line = yield result&lt;br /&gt;        for token in line.split():&lt;br /&gt;            try:&lt;br /&gt;                number = float(token)&lt;br /&gt;                stack[:0] = [number]&lt;br /&gt;                result = number&lt;br /&gt;            except ValueError:&lt;br /&gt;                try:&lt;br /&gt;                    result = {&lt;br /&gt;                        '+': lambda x, y: x + y,&lt;br /&gt;                        '-': lambda x, y: x - y,&lt;br /&gt;                        '*': lambda x, y: x * y,&lt;br /&gt;                        '/': lambda x, y: x / y&lt;br /&gt;                    }[token](stack[1], stack[0])&lt;br /&gt;                    stack[0:2] = [result]&lt;br /&gt;                except IndexError:&lt;br /&gt;                    raise ValueError, 'Stack is empty'&lt;br /&gt;                except KeyError:&lt;br /&gt;                    raise ValueError, 'Unknown operation'&lt;br /&gt;c = calc()&lt;br /&gt;c.next()&lt;br /&gt;&lt;br /&gt;for line in stdin.xreadlines():&lt;br /&gt;    print &amp;gt;&amp;gt; stdout, c.send(line)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Тут есть несколько необычных для новичка моментов.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;line = yield result&lt;/pre&gt; — это «вывернутый наизнанку» вызов функции, который позволяет разбить цикл обработки на две части: работу со стеком и получение строк со стандартного ввода. Команда yield возвращает значение подобно return, но функция при этом не завершается и будет продолжена при вызове метода send снаружи. причём, аргумент send будет передан через yield внутрь функции. Звучит запутанно, но &lt;a href="http://www.ibm.com/developerworks/ru/library/l-pycon/index.html"&gt;генераторы&lt;/a&gt; — это действительно очень мощная и гибкая штука.&lt;br /&gt;&lt;br /&gt;Другая необычность — использование индексирования словаря. Это позволяет ввести конструкцию, аналогичную, например, switch в C, без использования if—elif. Так код выглядит чище, хотя, конечно, тратятся ресурсы на создание анонимного словаря и поиск ключа в нём.&lt;br /&gt;&lt;br /&gt;Странные индексы списка stack с двоеточиями — это сечения (slices). Тоже довольно удобная штука. Они есть также в MatLab и Fortran, где без них программирование заметно усложнилось бы.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4154333943174084921-8726720007189103968?l=strange-to-say.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/SdoElkl8TLytwA-MWMm5GxohKI4/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/SdoElkl8TLytwA-MWMm5GxohKI4/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/SdoElkl8TLytwA-MWMm5GxohKI4/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/SdoElkl8TLytwA-MWMm5GxohKI4/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/zKMV/~4/XXnbGwmq3uY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://strange-to-say.blogspot.com/feeds/8726720007189103968/comments/default" title="Комментарии к сообщению" /><link rel="replies" type="text/html" href="http://strange-to-say.blogspot.com/2010/06/rpn-calculator.html#comment-form" title="Комментарии: 0" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4154333943174084921/posts/default/8726720007189103968?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4154333943174084921/posts/default/8726720007189103968?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/zKMV/~3/XXnbGwmq3uY/rpn-calculator.html" title="Обратный польский калькулятор / RPN Calculator" /><author><name>Вадим</name><uri>http://www.blogger.com/profile/03928284652612977325</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="30" height="32" src="http://1.bp.blogspot.com/_hRyhd7EUrGc/Sk5VleynHlI/AAAAAAAAAfE/ucW5wDwhBPw/S220/my_avatar.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://strange-to-say.blogspot.com/2010/06/rpn-calculator.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEYMR384fyp7ImA9WxNUFEs.&quot;"><id>tag:blogger.com,1999:blog-4154333943174084921.post-1365350861693218235</id><published>2009-11-05T19:29:00.012+02:00</published><updated>2009-11-06T01:03:06.137+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-11-06T01:03:06.137+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="linux" /><title>Как сделать deb-пакет со своими скриптами</title><content type="html">Рано или поздно у продвинутого пользователя линукса накапливается набор собственных скриптов, хранящихся где-то в «~/bin». Но каталог с программами не так красиво смотрится в домашнем каталоге, да и потом если делиться с друзьями, то приходится отправлять в архиве, говорить куда что копировать, убеждать их, что загромождение домашнего каталога — неизбежное зло. Можно, конечно и куда-то в «/usr/local/bin» их поместить, но можно потратить десять минут и собрать пакет, который потом легко устанавливается (и удаляется) штатными средствами. Причём туда, куда надо.&lt;br /&gt;&lt;br /&gt;Посмотрим, как это делается.&lt;br /&gt;&lt;span class="fullpost"&gt;&lt;br /&gt;В качестве примера скриптов возьмем, например следующие два.&lt;br /&gt;&lt;br /&gt;Первый загружает цитаты с &lt;a href="http://lorquotes.ru"&gt;lorquotes.ru&lt;/a&gt;.&lt;br /&gt;&lt;pre name='code' class='bash'&gt;#!/bin/sh&lt;br /&gt;[ -x ~/.lor ] || mkdir ~/.lor&lt;br /&gt;wget http://lorquotes.ru/fortraw.php -O -| iconv -f koi8-r -o ~/.lor/lor&lt;br /&gt;strfile ~/.lor/lor ~/.lor/lor.dat&lt;br /&gt;&lt;/pre&gt;А второй — выводит и при помощи утилиты fortune.&lt;br /&gt;&lt;pre name='code' class='bash'&gt;#!/bin/sh&lt;br /&gt;fortune ~/.lor&lt;/pre&gt;Назовем их соответственно «lor-update» и «lor».&lt;br /&gt;&lt;br /&gt;Сохраним их в отдельный каталог, который при сборке пакета должен иметь имя вида «пакет-версия». В нашем случае это будет «lorquotes-0.1».&lt;br /&gt;&lt;br /&gt;Теперь создадим заготовку пакета при помощи команды dh_make (есть в репозитории под именем — сюрприз! — «dh-make»). Для этого в нашем каталоге выполним следующую команду:&lt;br /&gt;&lt;pre&gt;dh_make --createorig -c gpl3 -e user@example.com -i -p lorquotes_0.1&lt;/pre&gt;Довольно длинно, не так ли? Разберём по порядку:&lt;br /&gt;--createorig — создать отдельную папку с исходниками, это будет нужно при создании пакета;&lt;br /&gt;-c gpl3 — указать в качестве лицензии GPL3 (какие ещё есть лицензии ,можно посмотреть в man-страничке утилиты dh_make);&lt;br /&gt;-e user@example.com — электронная почта собравшего пакет (то есть ваш);&lt;br /&gt;-i — говорим, что пакет не зависит от платформы (bash-скрипты везде одинаковы ведь);&lt;br /&gt;-p lorquotes_0.1 — указываем имя пакета (вообще, необязательно).&lt;br /&gt;&lt;br /&gt;Утилита спросит, всё ли она правильно поняла, на что мы честно соглашаемся и заходим в папку.&lt;br /&gt;&lt;br /&gt;Как видим, старое содержимое скопировалось в каталог «lorquotes-0.1.orig» (спасибо опции --createorig), а в «lorquotes-0.1» появился каталог «debian» с кучей файликов непонятного назначения. Собственно, содержимое этого каталога и определяет как будет вести себя пакет при установке и что он будет содержать.&lt;br /&gt;&lt;br /&gt;Но сперва нужно создать мейкфайл. Это специальный файл, имеющий имя Makefile и говорящий сборщику пакета, как скомпилировать исходнуе тексты и куда устанавливать его содержимое. Структура нашего мейкфайла очень проста:&lt;br /&gt;&lt;pre&gt;DESTDIR =&lt;br /&gt;BIN = $(DESTDIR)/usr/bin&lt;br /&gt;&lt;br /&gt;build:&lt;br /&gt; true&lt;br /&gt;&lt;br /&gt;install:&lt;br /&gt; install -d $(BIN)&lt;br /&gt; install -m755 lor $(BIN)&lt;br /&gt; install -m755 lor-update $(BIN)&lt;/pre&gt;Заметьте, что некоторые строки набраны с отступом при помощи табуляции. Именно так и нужно набирать. Это важно!&lt;br /&gt;&lt;br /&gt;Мейкфайл — это просто предписание команде «make» выполнить определенный набор действий.&lt;br /&gt;&lt;br /&gt;В строке 1 определены специальные переменные: DESTDIR — каталог, в который будет устанавливаться наш пакет. Эта переменная обязательно должна быть в мейкфайле, так как черех неё потом сборщик пакета указывает каталог назначения.&lt;br /&gt;&lt;br /&gt;В строке 2 указан каталог, куда будут установлены наши скрипты. Без этой переменной уже можно было обойтись, так как она пользовательская и введена для удобства.&lt;br /&gt;&lt;br /&gt;Строка с «build» — это одна из целей, которых должен достичь make. После двоеточия можно было указать список целей, от которых цель «build» зависит, но у нас и компилировать-то нечего, потому ничего и не указано. После цели идут команды (внимание, с отступом!), которые необходимо выполнить для достижения этой цели. Так как ничего выполнять не надо, то там стоит команда true, которая ничего не делает (такая у неё работа).&lt;br /&gt;&lt;br /&gt;Аналогично описана цель «install». Но тут уже нужны действия: а именно создание каталога назначения и копирование в него с соответствующими правами наших скриптов. Вместо обычных команд создания и копирования используется утилита install, которая более интеллектуальна и специально для этих целей предназначена.&lt;br /&gt;&lt;br /&gt;Итак, создаем в папке со скриптами (не в debian) мейкфайл под именем Makefile. Теперь мы можем при помощи команд «make» (ничего не делает, т.к выполнится первая цель в файле, т.е. «build») и «sudo make install» (копирует скрипты куда надо) собрать и установить вручную наши скрипты. Но вручную нам не нужно, мы ведь пакет хотим собрать. Поэтому переходим к следующему этапу.&lt;br /&gt;&lt;br /&gt;Настроим свойства нашего пакета. Перейдём в каталог «debian» и откроем файл «control». Он содержит информацию о пакете, его зависимостях и так далее. Заполним его как анкету.&lt;br /&gt;&lt;br /&gt;Source — название того, что мы сейчас собираем,&lt;br /&gt;Section — в какую секцию дерева репозитория поместить наш пакет,&lt;br /&gt;Priority — важность пакета,&lt;br /&gt;Maintainer — сборщик,&lt;br /&gt;Build-Depends — какие программы нужны для сборки пакета,&lt;br /&gt;Standards-Version — версия стандарта, описывающего сборку пакетов,&lt;br /&gt;Homepage — домашняя страничка (если есть),&lt;br /&gt;Package — имя собственно deb-пакета,&lt;br /&gt;Architecture — архитектура, под которую он собирается (i386, amd64 и иже с ними),&lt;br /&gt;Depends — от каких пакетом наш зависит,&lt;br /&gt;Description — описание, короткое в той же строке и длинное ниже (обратите внимание на пробел в начале строки с длинным описанием).&lt;br /&gt;&lt;br /&gt;Я для примера сделал такой файл:&lt;br /&gt;&lt;pre&gt;Source: lorquotes&lt;br /&gt;Section: misc&lt;br /&gt;Priority: optional&lt;br /&gt;Maintainer: Vasiliy Pupkin &lt;vasiliy@example.com&gt;&lt;br /&gt;Build-Depends: debhelper (&gt;= 7)&lt;br /&gt;Standards-Version: 3.8.3&lt;br /&gt;Homepage: http://pupkin.example.com/lorquotes/&lt;br /&gt;&lt;br /&gt;Package: lorquotes&lt;br /&gt;Architecture: all&lt;br /&gt;Depends: wget,fortunes&lt;br /&gt;Description: Small LOR quotes utility&lt;br /&gt; Shows you random quote from lorquotes.ru.&lt;/pre&gt;Думаю, указывать в зависимостях шелл и libc6 смысла нет. Они точно есть в любой системе (или нет?).&lt;br /&gt;&lt;br /&gt;Теперь подправим файл «changelog». Он содержит историю версия нашего пакета. Во время правки не забывайте, что он тоже имеет строгий формат и не добавляйте лишние отступы и строки.&lt;br /&gt;&lt;br /&gt;Вот мой вариант:&lt;br /&gt;&lt;pre&gt;lorquotes (0.1-1) unstable; urgency=low&lt;br /&gt;&lt;br /&gt;  * Initial release&lt;br /&gt;&lt;br /&gt; -- Vasiliy Pupkin &lt;vasiliy@example.com&gt;  Thu, 05 Nov 2009 19:53:58 +0200&lt;/pre&gt;unstable — это имя ветки дистрибутива, для которой готовится пакет, а urgency — это приоритет.&lt;br /&gt;&lt;br /&gt;В том же каталоге есть файл «rules». Это обычный мекфайл, который и отвечает за конфигурирование и сборку пакета. Но так как мы ничего экстраординарного не делали, оставим всё как есть.&lt;br /&gt;&lt;br /&gt;В файле «copyright» находится лицензия. Мы лицензию сразу указали, так что и этот файл трогать не будем.&lt;br /&gt;&lt;br /&gt;Итак, остались ещё следующие важные для нас файлы.&lt;br /&gt;&lt;br /&gt;«cron.d.ex». Переименовываем его в «cron.d». Он содержит информацию о регулярных действиях, которые будет выполнять установленная программа. В нашем случае — ежедневное обновление базы цитат в полдень:&lt;pre&gt;#&lt;br /&gt;# Regular cron jobs for the lorquotes package&lt;br /&gt;#&lt;br /&gt;0 12 * * * root [ -x /usr/bin/lor-update ] &amp;&amp; /usr/bin/lor-update&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;«postrm.ez». Переименовываем в «postrm». Это скрипт, запускаемый после удаления пакета. Заставим его очищать нашу базу цитат, хранящуюся в «~/.lor». Хотя хранить базу в домашнем каталоге не совсем верно идеологически. Но, думаю, после этого поста читатель и сам исправит эту неточность. Итак, мой «postrm»:&lt;pre&gt;#!/bin/sh&lt;br /&gt;# postrm script for lorquotes&lt;br /&gt;#&lt;br /&gt;# see: dh_installdeb(1)&lt;br /&gt;&lt;br /&gt;set -e&lt;br /&gt;&lt;br /&gt;case "$1" in&lt;br /&gt;    purge|remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear)&lt;br /&gt;    rm -rf ~/.lor&lt;br /&gt;    ;;&lt;br /&gt;&lt;br /&gt;    *)&lt;br /&gt;        echo "postrm called with unknown argument \`$1'" &gt;&amp;2&lt;br /&gt;        exit 1&lt;br /&gt;    ;;&lt;br /&gt;esac&lt;br /&gt;&lt;br /&gt;# dh_installdeb will replace this with shell code automatically&lt;br /&gt;# generated by other debhelper scripts.&lt;br /&gt;&lt;br /&gt;#DEBHELPER#&lt;br /&gt;&lt;br /&gt;exit 0&lt;/pre&gt;Остальные файлы нам не нужны и смело их удаляем. Это разные заготовки. Например, для man-страниц.&lt;br /&gt;&lt;br /&gt;Переходим теперь в каталог со скриптами (т.е. на уровень выше) и даём команду на сбору пакета:&lt;br /&gt;&lt;pre&gt;debuild&lt;/pre&gt;Она собирает пакет, проверяет на ошибки, а потом пробует его подписать вашим GPG-ключом. Но даже если ей подписать не удастся, пакет будет собран. Найти его можно будет в каталоге уровнем выше. Там же будет архив с исходниками и вспомогательные файлы, нужные, если вы хотите создать свой репозиторий или загрузить пакет в уже существующий.&lt;br /&gt;&lt;br /&gt;Конечно, при сборке пакета будут предупреждения. Но мы ведь не закачивать его в дебиановский репозиторий будем, а для себя собираем. Так что устранение причин предупреждений остаётся в качестве домашнего задания читателю. (Кстати, это несложно.)&lt;br /&gt;&lt;br /&gt;Вот и всё! Осталось только установить пакет. :)&lt;br /&gt;&lt;br /&gt;Как видите, ничего сложного. Если интересуют подробности или захотелось собрать пакет позаковыристее, милости просим на &lt;a href="http://www.debian.org/doc/manuals/maint-guide/index.ru.html"&gt;соответствующую страничку&lt;/a&gt; дебиановской документации.&lt;br /&gt;&lt;br /&gt;А вот &lt;a href="http://narod.ru/disk/14807417000/lorquotes_0.1.zip.html"&gt;архив&lt;/a&gt; с исходниками и пакетом.&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4154333943174084921-1365350861693218235?l=strange-to-say.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/Nzd2BIjtl7qXSPKVDziz3lTtP2M/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Nzd2BIjtl7qXSPKVDziz3lTtP2M/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/Nzd2BIjtl7qXSPKVDziz3lTtP2M/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Nzd2BIjtl7qXSPKVDziz3lTtP2M/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/zKMV/~4/SnyJ8iLZarA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://strange-to-say.blogspot.com/feeds/1365350861693218235/comments/default" title="Комментарии к сообщению" /><link rel="replies" type="text/html" href="http://strange-to-say.blogspot.com/2009/11/deb.html#comment-form" title="Комментарии: 1" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4154333943174084921/posts/default/1365350861693218235?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4154333943174084921/posts/default/1365350861693218235?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/zKMV/~3/SnyJ8iLZarA/deb.html" title="Как сделать deb-пакет со своими скриптами" /><author><name>Вадим</name><uri>http://www.blogger.com/profile/03928284652612977325</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="30" height="32" src="http://1.bp.blogspot.com/_hRyhd7EUrGc/Sk5VleynHlI/AAAAAAAAAfE/ucW5wDwhBPw/S220/my_avatar.gif" /></author><thr:total>1</thr:total><feedburner:origLink>http://strange-to-say.blogspot.com/2009/11/deb.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C04ERHw9eCp7ImA9WxNUEUU.&quot;"><id>tag:blogger.com,1999:blog-4154333943174084921.post-3151807369865007716</id><published>2009-11-02T12:05:00.006+02:00</published><updated>2009-11-02T19:11:45.260+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-11-02T19:11:45.260+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="сеть" /><category scheme="http://www.blogger.com/atom/ns#" term="linux" /><category scheme="http://www.blogger.com/atom/ns#" term="python" /><title>Отправка email из командной строки</title><content type="html">О том &lt;a href="http://strange-to-say.blogspot.com/2009/11/jabber.html"&gt;как отправлять сообщения через jabber&lt;/a&gt;, я уже написал. А вот сегодня мне захотелось написать утилитку, которая бы делала то же самое и с теми же (примерно) параметрами командной строки, но для электронной почты. Конечно, в линуксе полно консольных почтовых программ (я в курсе, что есть команда mail), но мне не нужны все их возможности, а кроме того, хотелось бы ещё и кроссплатформенности (я в курсе, что в Windows есть утилита blat) и возможности быстро самому что-то дописать. Вот, что получилось. &lt;br /&gt;&lt;span class="fullpost"&gt;&lt;br /&gt;Не буду тянуть, сразу приведу код скрипта.&lt;br /&gt;&lt;pre  name='code' class='python'&gt;#!/usr/bin/env python&lt;br /&gt;import smtplib, ConfigParser, email.mime.text, getopt, os, sys, locale&lt;br /&gt;&lt;br /&gt;name = os.path.basename(sys.argv[0])&lt;br /&gt;&lt;br /&gt;optlist, args = getopt.getopt(sys.argv[1:], 's:f:')&lt;br /&gt;if len(args) &lt; 2:&lt;br /&gt;    print "Send a message via email"&lt;br /&gt;    print&lt;br /&gt;    print "Syntax:", name, "[-f from] [-s subject] email text"&lt;br /&gt;    print "email\trecipient's e-mail address"&lt;br /&gt;    print "from\tsender's email"&lt;br /&gt;    print "subject\tmessage subject"&lt;br /&gt;    print "text\tmessage, use '-' for stdin"&lt;br /&gt;    sys.exit(0)&lt;br /&gt;&lt;br /&gt;configFile = os.path.join(os.environ['HOME'], '.' + name)&lt;br /&gt;config = ConfigParser.RawConfigParser()&lt;br /&gt;try:&lt;br /&gt;    config.read(configFile)&lt;br /&gt;    fromEmail = config.get('From', 'E-mail')&lt;br /&gt;    smtpServer = config.get('SMTP', 'Server')&lt;br /&gt;    smtpLogin = config.get('SMTP', 'Login')&lt;br /&gt;    smtpPassword = config.get('SMTP', 'Password')&lt;br /&gt;except:&lt;br /&gt;    print "Default configuration was written to", configFile&lt;br /&gt;    config.add_section('From')&lt;br /&gt;    config.set('From', 'E-mail', 'user@example.com')&lt;br /&gt;    config.add_section('SMTP')&lt;br /&gt;    config.set('SMTP', 'Server', 'smtp.example.com')&lt;br /&gt;    config.set('SMTP', 'Login', 'user')&lt;br /&gt;    config.set('SMTP', 'Password', '********')&lt;br /&gt;    f = file(configFile, 'w')&lt;br /&gt;    config.write(f)&lt;br /&gt;    f.close()&lt;br /&gt;    sys.exit(0)&lt;br /&gt;&lt;br /&gt;toEmail = args[0]&lt;br /&gt;subject = ''&lt;br /&gt;for option, value in optlist:&lt;br /&gt;    if option == '-s':&lt;br /&gt;        subject = value&lt;br /&gt;    elif option == '-f':&lt;br /&gt;        fromEmail = value&lt;br /&gt;&lt;br /&gt;encoding = locale.getpreferredencoding()&lt;br /&gt;if args[1] == '-':&lt;br /&gt;    message = email.mime.text.MIMEText(sys.stdin.read(), 'plain', encoding)&lt;br /&gt;else:&lt;br /&gt;    message = email.mime.text.MIMEText(' '.join(args[1:]), 'plain', encoding)&lt;br /&gt;&lt;br /&gt;message['Subject'] = subject&lt;br /&gt;message['From'] = fromEmail&lt;br /&gt;message['To'] = toEmail&lt;br /&gt;&lt;br /&gt;server = smtplib.SMTP(smtpServer)&lt;br /&gt;server.login(smtpLogin, smtpPassword)&lt;br /&gt;server.sendmail(message['From'], message['To'], message.as_string())&lt;br /&gt;server.quit()&lt;/pre&gt;Всё это сохраняем в файл с именем, например, «mailto» и даём права на выполнение:&lt;br /&gt;&lt;pre&gt;chmod +x mailto&lt;/pre&gt;После первого создаётся файл с настройками подключения. По умолчанию это файл «.mailto» (если скрипт называется «mailto», конечно) в домашнем каталоге. В нём нужно указать адрес отправителя и настройки smtp-сервера.&lt;br /&gt;&lt;br /&gt;Параметров у скрипта минимум, только то, что нужно. Есть два опциональных для указания темы сообщения и адреса отправителя (по умолчанию берётся из файла с настройками). Для них используются ключи «-s» и «-f» соответственно (от слов «From» и «Subject»).&lt;br /&gt;&lt;br /&gt;Обязательных параметров всего два и они без ключей. Это адрес получателя собственно текст сообщения. Если вместо текста поставить «-», то текст будет браться из стандартного входа, что удобно для отправки результатов вывода какой-то программы.&lt;br /&gt;&lt;br /&gt;Использовать программу можно для чего угодно. Например, чтобы отправить список пользователей себе на ящик можно воспользоваться командой:&lt;br /&gt;&lt;pre&gt;who | mailto user@example.com -&lt;/pre&gt;Я, например, использую этот скрипт, чтобы автоматически в определённое время слать себе СМС с напоминанием о чём-либо через гейт «email—SMS» моего мобильного оператора. Получилось удобно.&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4154333943174084921-3151807369865007716?l=strange-to-say.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/c5AZNZNgneZk3BcAgXoivQfSufg/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/c5AZNZNgneZk3BcAgXoivQfSufg/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/c5AZNZNgneZk3BcAgXoivQfSufg/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/c5AZNZNgneZk3BcAgXoivQfSufg/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/zKMV/~4/bbdQ5C1zL9A" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://strange-to-say.blogspot.com/feeds/3151807369865007716/comments/default" title="Комментарии к сообщению" /><link rel="replies" type="text/html" href="http://strange-to-say.blogspot.com/2009/11/email.html#comment-form" title="Комментарии: 1" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4154333943174084921/posts/default/3151807369865007716?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4154333943174084921/posts/default/3151807369865007716?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/zKMV/~3/bbdQ5C1zL9A/email.html" title="Отправка email из командной строки" /><author><name>Вадим</name><uri>http://www.blogger.com/profile/03928284652612977325</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="30" height="32" src="http://1.bp.blogspot.com/_hRyhd7EUrGc/Sk5VleynHlI/AAAAAAAAAfE/ucW5wDwhBPw/S220/my_avatar.gif" /></author><thr:total>1</thr:total><feedburner:origLink>http://strange-to-say.blogspot.com/2009/11/email.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUYDRXY8fCp7ImA9WxNUEk0.&quot;"><id>tag:blogger.com,1999:blog-4154333943174084921.post-7675900553010352787</id><published>2009-11-01T00:44:00.016+02:00</published><updated>2009-11-03T01:06:14.874+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-11-03T01:06:14.874+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="jabber" /><category scheme="http://www.blogger.com/atom/ns#" term="сеть" /><category scheme="http://www.blogger.com/atom/ns#" term="linux" /><category scheme="http://www.blogger.com/atom/ns#" term="python" /><category scheme="http://www.blogger.com/atom/ns#" term="консоль" /><title>Отправка jabber-сообщений из командной строки</title><content type="html">О том, как отправить jabber-сообщение из консоли при помощи клиента Gajim, я уже писал &lt;a href="http://strange-to-say.blogspot.com/2009/07/gajim.html"&gt;ранее&lt;/a&gt;. Тем не менее, использование gajim-remote имеет ряд недостатков: нужно установить сам Gajim и запустить его. Это может вызвать некоторые затруднения, например, на сервере, где вовсе может не быть графического интерфейса. Однако, проблема имеет и более простое решение.&lt;br /&gt;&lt;span class="fullpost"&gt;&lt;br /&gt;Сделаем скрипт, которому бы в качестве параметров передавались данные учётной записи jabber, JID отправителя и текст сообщения. В качестве основы возьмём питоновскую библиотеку &lt;a href="http://xmpppy.sourceforge.net/"&gt;xmpppy&lt;/a&gt;. В частности, рассмотрим повнимательнее один из примеров, входящих в её комплект, который (сюрприз!) как раз и предназначен для отправки сообщений из консоли. Остаётся только его чуть-чуть «допилить» по вкусу.&lt;br /&gt;&lt;br /&gt;Итак, нам потребуется библиотека. Они есть в репозиториях Debian (да и других популярных дистрибутивов), поэтому устанавливаем как обычно:&lt;br /&gt;&lt;pre&gt;sudo aptitude install python-xmpp python-dnspython&lt;/pre&gt;Без python-dnspython работать тоже будет, кстати. Но лучше поставить, так как в этом случае придётся вводить точное имя узла, на котором располагается сервер.&lt;br /&gt;&lt;br /&gt;А вот и сам скрипт:&lt;br /&gt;&lt;pre name='code' class='python'&gt;#!/usr/bin/env python&lt;br /&gt;import sys,os,xmpp,time,ConfigParser&lt;br /&gt;&lt;br /&gt;name = os.path.basename(sys.argv[0])&lt;br /&gt;&lt;br /&gt;if len(sys.argv) &lt; 2:&lt;br /&gt;    print "Send a message via Jabber (XMPP)"&lt;br /&gt;    print "Syntax:", name, "JID text"&lt;br /&gt;    print "JID\trecipient's Jabber ID"&lt;br /&gt;    print "text\tmessage, use '-' for stdin"&lt;br /&gt;    sys.exit(0)&lt;br /&gt;&lt;br /&gt;toJID = sys.argv[1]&lt;br /&gt;if sys.argv[2] == '-':&lt;br /&gt;    text = sys.stdin.read()&lt;br /&gt;else:&lt;br /&gt;    text = ' '.join(sys.argv[2:])&lt;br /&gt;&lt;br /&gt;configFile = os.path.join(os.environ['HOME'], '.' + name)&lt;br /&gt;config = ConfigParser.RawConfigParser()&lt;br /&gt;&lt;br /&gt;try:&lt;br /&gt;    config.read(configFile)&lt;br /&gt;    fromJID = config.get('Connection', 'JID')&lt;br /&gt;    password = config.get('Connection', 'Password')&lt;br /&gt;except:&lt;br /&gt;    print "Default configuration was written to", configFile&lt;br /&gt;    config.add_section('Connection')&lt;br /&gt;    config.set('Connection', 'JID', 'user@example.com/home')&lt;br /&gt;    config.set('Connection', 'Password', '********')&lt;br /&gt;    f = file(configFile, 'w')&lt;br /&gt;    config.write(f)&lt;br /&gt;    f.close()&lt;br /&gt;    sys.exit(0)&lt;br /&gt;&lt;br /&gt;fromJID = xmpp.protocol.JID(fromJID)&lt;br /&gt;client = xmpp.Client(fromJID.getDomain(),debug=[])&lt;br /&gt;&lt;br /&gt;conn = client.connect()&lt;br /&gt;if not conn:&lt;br /&gt;    print 'Could not connect!'&lt;br /&gt;    sys.exit(1)&lt;br /&gt;print 'Connected with', conn&lt;br /&gt;&lt;br /&gt;auth = client.auth(fromJID.getNode(), password, resource=fromJID.getResource())&lt;br /&gt;if not auth:&lt;br /&gt;    print 'Could not authenticate!'&lt;br /&gt;    sys.exit(1)&lt;br /&gt;print 'Authenticated using', auth&lt;br /&gt;&lt;br /&gt;messageID = client.send(xmpp.protocol.Message(toJID, text))&lt;br /&gt;print 'Message was sent'&lt;br /&gt;&lt;br /&gt;time.sleep(1)&lt;br /&gt;client.disconnect()&lt;br /&gt;&lt;/pre&gt;Скрипт довольно простой, так что разбирать его работу не буду.&lt;br /&gt;&lt;br /&gt;Всё это сохраняем в каталог «~/bin» под именем, например, «jsend». Имя и каталог значения не имеют, просто «~/bin» удобен для хранения пользовательских скриптов, так как он входит в переменную PATH и для запуска скритов из него достаточно указать их имена. В любом случае нужно разрешить выполнение нашей программки:&lt;br /&gt;&lt;pre&gt;chmod +x jsend&lt;/pre&gt;Рассмотрим её работу. После первого запуска утилита создаёт в домашнем каталоге файл с JID и паролем отправителя. Это удобнее, чем вводить пароль в качестве параметра командной строки, так как в этом случае никто не сможет его подсмотреть. Да и доступ к файлу можно будет закрыть. Файл поличит имя, совпадающее с именем скрипта, но с точкой впереди, чтобы не отображаться лишний раз в списке файлов. В моём случае имя будет «~/.jsend». Естественно, файл после первого запуска нужно будет открыть и впесать свои JID и пароль.&lt;br /&gt;&lt;br /&gt;Формат запуска скрипта:&lt;br /&gt;&lt;pre&gt;jsend JID text&lt;/pre&gt;JID — это идентификатор получателя сообщения, а text — это собственно текст, который нужно отправить.&lt;br /&gt;&lt;br /&gt;Если текста много или нужно отправить вывод какой-либо команды, то вместо text можно поставить «-». Например, команда&lt;br /&gt;&lt;pre&gt;df | jsend user@example.com -&lt;/pre&gt;отправит информацию о заполненности разделов на дисках пользователю user@example.com.&lt;br /&gt;&lt;br /&gt;Также можно настроить отправку сообщений в определённое время при помощи команды at, что тоже иногда оказывается удобным.&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4154333943174084921-7675900553010352787?l=strange-to-say.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/Z_UNtHoMVM2OuMPeVJ7hWrc1GNQ/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Z_UNtHoMVM2OuMPeVJ7hWrc1GNQ/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/Z_UNtHoMVM2OuMPeVJ7hWrc1GNQ/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Z_UNtHoMVM2OuMPeVJ7hWrc1GNQ/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/zKMV/~4/kIhhWqkJ5Ok" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://strange-to-say.blogspot.com/feeds/7675900553010352787/comments/default" title="Комментарии к сообщению" /><link rel="replies" type="text/html" href="http://strange-to-say.blogspot.com/2009/11/jabber.html#comment-form" title="Комментарии: 0" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4154333943174084921/posts/default/7675900553010352787?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4154333943174084921/posts/default/7675900553010352787?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/zKMV/~3/kIhhWqkJ5Ok/jabber.html" title="Отправка jabber-сообщений из командной строки" /><author><name>Вадим</name><uri>http://www.blogger.com/profile/03928284652612977325</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="30" height="32" src="http://1.bp.blogspot.com/_hRyhd7EUrGc/Sk5VleynHlI/AAAAAAAAAfE/ucW5wDwhBPw/S220/my_avatar.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://strange-to-say.blogspot.com/2009/11/jabber.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkUBQ306fCp7ImA9WxFVFU8.&quot;"><id>tag:blogger.com,1999:blog-4154333943174084921.post-8426104388925106253</id><published>2009-10-27T21:16:00.013+02:00</published><updated>2010-06-14T18:10:52.314+03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-06-14T18:10:52.314+03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="звук" /><category scheme="http://www.blogger.com/atom/ns#" term="linux" /><title>Разрезаем lossless-аудио (ape, flac, wv, wav) по файлу cue</title><content type="html">Понимаю, что теме этого поста наверняка написано огромное количество статей, мануалов и прочих ЧаВо. Но каждый раз искать лень, проще один раз сделать узелок на память в блоге.&lt;br /&gt;&lt;br /&gt;(Это перевод англоязычной заметки. См. также &lt;a href="http://strange-to-say.blogspot.com/2010/06/lossless-ape-flac-wv-wav-cue.html"&gt;описание более простого способа&lt;/a&gt;.)&lt;br /&gt;&lt;br /&gt;Итак, задача такова: дана пара файлов, предположим sample.cue и sample.flac, с каким-либо альбомом. Требуется получить треки альбома в отдельных flac-файлах.Если у вас linux, то делается это в два счёта. Ниже следует перевод одной довольно неплохой статьи с решением проблемы.&lt;br /&gt;&lt;br /&gt;&lt;span class="fullpost"&gt;&lt;br /&gt;Файлы с lossless-аудио могут быть разрезаны по cue-файлу при помощи утилиты «shnsplit» (входит в пакет «shntool»). Также потребуется утилита «cuebreakpoints» (из пакета «cuetools»). Чтобы установить их, откройте терминал и введите следующее (&lt;span style="font-style:italic;"&gt;эти пакеты есть в Ubuntu и Debian&lt;/span&gt;):&lt;br /&gt;&lt;pre&gt;sudo apt-get install cuetools shntool&lt;/pre&gt;&lt;br /&gt;Кроме этого потребуются приложения для работы с выбранным форматом. Для Monkey’s Audio нужна будет утилита «mac» (&lt;span style="font-style:italic;"&gt;в Debian есть пакет «monkeys-audio»&lt;/span&gt;). Для FLAC и WavePack потребуется установить соответственно «flac» и «wavpack»:&lt;br /&gt;&lt;pre&gt;sudo apt-get install flac wavpack&lt;/pre&gt;&lt;br /&gt;Утилите shnsplit требуется для работы список точек, в которых нужно делить звуковой файл. Очень кстати тут оказывается утилита cuebreakpoints, которая печатает список таких точек по cue- или toc-файлу в формате, используемом в shnsplit. Можно создать конвейер между cuebreakpoints и shnsplit следующим образом:&lt;br /&gt;&lt;pre&gt;cuebreakpoints sample.cue | shnsplit -o flac sample.flac&lt;/pre&gt;&lt;br /&gt;В этом примере flac-файл с именем «sample.flac» разрезается по точкам, содержащимся в «sample.cue» и результат выводится в формате FLAC.&lt;br /&gt;&lt;br /&gt;Выходной формат задаётся параметром «-o». Если не указать формат, то файлы будут сохрняться в формате по умолчанию, то есть в виде wav-файлов.&lt;br /&gt;&lt;br /&gt;Чтобы разрезать файл в формате Monkey’s Audio и сохраниеть результаты в формате FLAC, нужно выполнить следующую команду:&lt;br /&gt;&lt;pre&gt;cuebreakpoints sample.cue | shnsplit -o flac sample.ape&lt;/pre&gt;&lt;br /&gt;По умолчанию для выходных файлов используется префикс «split-track» (то есть по умолчанию файлы будут иметь имена: split-track01, split-track02, split-track03,…). Можно задать собственный префикс при помощи опции «-a».&lt;br /&gt;&lt;br /&gt;Чтобы посмотреть список всех параметров наберите «shntool split -h» или «shnsplit -h».&lt;br /&gt;&lt;br /&gt;В звуковые файлах, полученных с помощью shnsplit не будут записаны данные об исполнителе, альбоме и так далее. Однако, можно воспользоваться скриптом cuetag (также входящим в пакет cuetools) для того, чтобы перенести данные из cue-файла в отдельные дорожки. Можно указать отдельные файлы, соответствующие дорожкам, содержащимся в cue-файле:&lt;br /&gt;&lt;pre&gt;cuetag sample.cue split-track01.flac split-track02.flac split-track03.flac split-track04.flac&lt;/pre&gt;&lt;br /&gt;Эта команда перенесёт теги, содержащиеся в файле «sample.cue» в файлы с дорожками: «split-track01.flac», «split-track02.flac», «split-track03.flac» and «split-track04.flac».&lt;br /&gt;Можно записать теги сразу во все полученные файлы:&lt;br /&gt;&lt;pre&gt;cuetag sample.cue split-track*.flac&lt;/pre&gt;&lt;br /&gt;Утилита cuetag работает с форматами FLAC, Ogg и mp3.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://aidanjm.wordpress.com/2007/02/15/split-lossless-audio-ape-flac-wv-wav-by-cue-file/"&gt;Источник&lt;/a&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4154333943174084921-8426104388925106253?l=strange-to-say.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/ZKrR-6iX6WO8UQCeUdossAOjAks/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/ZKrR-6iX6WO8UQCeUdossAOjAks/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/ZKrR-6iX6WO8UQCeUdossAOjAks/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/ZKrR-6iX6WO8UQCeUdossAOjAks/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/zKMV/~4/eiWnmnn-ByQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://strange-to-say.blogspot.com/feeds/8426104388925106253/comments/default" title="Комментарии к сообщению" /><link rel="replies" type="text/html" href="http://strange-to-say.blogspot.com/2009/10/lossless-ape-flac-wv-wav-cue.html#comment-form" title="Комментарии: 4" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4154333943174084921/posts/default/8426104388925106253?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4154333943174084921/posts/default/8426104388925106253?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/zKMV/~3/eiWnmnn-ByQ/lossless-ape-flac-wv-wav-cue.html" title="Разрезаем lossless-аудио (ape, flac, wv, wav) по файлу cue" /><author><name>Вадим</name><uri>http://www.blogger.com/profile/03928284652612977325</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="30" height="32" src="http://1.bp.blogspot.com/_hRyhd7EUrGc/Sk5VleynHlI/AAAAAAAAAfE/ucW5wDwhBPw/S220/my_avatar.gif" /></author><thr:total>4</thr:total><feedburner:origLink>http://strange-to-say.blogspot.com/2009/10/lossless-ape-flac-wv-wav-cue.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Ck8NQ3syeCp7ImA9WxJbF08.&quot;"><id>tag:blogger.com,1999:blog-4154333943174084921.post-6648849086084415891</id><published>2009-07-27T20:45:00.005+03:00</published><updated>2009-07-27T21:54:52.590+03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-07-27T21:54:52.590+03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="jabber" /><category scheme="http://www.blogger.com/atom/ns#" term="linux" /><category scheme="http://www.blogger.com/atom/ns#" term="утилиты" /><title>Управляем Gajim из командной строки</title><content type="html">Gajim — это популярный и активно развивающийся Jabber-клиент, написанный на Python. К слову, он обладает очень неплохой поддержкой всевозможных вкусностей и полезностей Jabber по сравнению со многими другими клиентами. Одной из таких полезностей является возможность управления им из командной строки при помощи &lt;a href="http://ru.wikipedia.org/wiki/D-Bus"&gt;D-Bus&lt;/a&gt; — системы межпроцессного взаимодействия.&lt;br /&gt;&lt;br /&gt;Управление из командной строки не означает, что Gajim имеет консольный интерфейс. Он по-прежнему будет располагаться на рабочем столе в виде окошка. Просто из консоли можно будет отправлять ему какие-либо команды. Собственно, команд поддерживается немного, но для каких-то простейших действий должно хватить.&lt;br /&gt;&lt;span class="fullpost"&gt;&lt;br /&gt;В состав пакета с Gajim входит консольная утилитка gajim-remote, которая как раз и предназначена для отправки команд основной программе. Если вызвать её без параметров, она покажет список поддерживаемых действий. Вот наиболее интересные:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;check_gajim_running — проверить, запущен ли Gajim (результат — True или False),&lt;/li&gt;&lt;li&gt;list_accounts — список учётных записей,&lt;/li&gt;&lt;li&gt;list_contacts [учётные записи] — список контактов в учётных записях,&lt;/li&gt;&lt;li&gt;contact_info &amp;lt;jid&amp;gt; — информация о пользователе с указанным JID,&lt;/li&gt;&lt;li&gt;account_info &lt;учётная запись&gt; — показать информацию об одной из учётных записей Gajim,&lt;/li&gt;&lt;li&gt; add_contact &amp;lt;jid&amp;gt; [учётные записи] — добавить контакт в ростер,&lt;/li&gt;&lt;li&gt;remove_contact &amp;lt;jid&amp;gt; [учётные записи] — удалить учётную запись из ростера,&lt;/li&gt;&lt;li&gt;change_status &amp;lt;статус&amp;gt; [сообщение] [учётные записи] — изменить статус с возможностью указания сообщения и учётной записи (если не указать — будет изменен статус всех учётных записей),&lt;/li&gt;&lt;li&gt;get_status [учётные записи] — получить статус указанных учётных записей,&lt;/li&gt;&lt;li&gt;get_status_message [учётные записи] — получить сообщение статуса указанных учётных записей,&lt;/li&gt;&lt;li&gt;get_unread_msgs_number — количество непрочитанных сообщений,&lt;/li&gt;&lt;li&gt;handle_uri &amp;lt;uri&amp;gt; [учётные записи] — обработать ссылку вида «xmpp://»,&lt;/li&gt;&lt;li&gt;join_room &lt;комната&gt; [ник] [пароль:] [учётные записи] — присоединиться к конференции,&lt;/li&gt;&lt;li&gt;send_chat_message &amp;lt;jid&amp;gt; &amp;lt;сообщение&amp;gt; [PGP-ключ] [учётные записи] — отправить сообщение в чат,&lt;/li&gt;&lt;li&gt;send_file &amp;lt;файл&amp;gt; &amp;lt;jid&amp;gt; [учётные записи] — отправить файл,&lt;/li&gt;&lt;li&gt;send_groupchat_message &amp;lt;jid&amp;gt; &amp;lt;сообщение&amp;gt; [учётные записи] — отправить сообщение в конференцию,&lt;/li&gt;&lt;li&gt;send_single_message &amp;lt;jid&amp;gt; &amp;lt;тема&amp;gt; &amp;lt;сообщение&amp;gt; [PGP-ключ] [учётные записи] — отправить одиночное сообщение,&lt;/li&gt;&lt;li&gt;open_chat &amp;lt;jid&amp;gt; [учётные записи] — открыть чат с указанным контактом,&lt;/li&gt;&lt;li&gt;start_chat &amp;lt;учётные записи&amp;gt; — открыть чат для заданной учётной записи (появится окно ввода JID),&lt;/li&gt;&lt;li&gt;toggle_roster_appearance — показать/скрыть окошко ростера.&lt;/li&gt;&lt;/ul&gt;Попробуем теперь применить это на практике. Напишем скрипт, меняющий сообщение статуса на случайную цитату из fortunes. (Для тех, кто ещё не знает, fortunes — это консольная программа, выдающая случайную цитату из довольно объемной базы.)&lt;br /&gt;&lt;br /&gt;Для этого в бесконечном цикле будем вызывать gajim-remote, передавая ему при помощи обратных кавычек результат выполнения команды fortunes. Между вызовами поставим паузу 5 минут (5×60=300 с).&lt;br /&gt;&lt;pre&gt;while true; do gajim-remote change_status "online" "`fortune`"; sleep 300; done&lt;/pre&gt;У этой команды есть небольшой недостаток — нужно всё время держать терминал открытым. Для того, чтобы решить эту проблему, можно просто записать команду в текстовый файл, а потом запустить следующим образом:&lt;br /&gt;&lt;pre&gt;bash changestatus.sh &amp;amp;&lt;/pre&gt;Амперсанд в конце запустит выполнение скрипта в фоне. Можно также создать правило для cron — тогда вообще не придется что-либо запускать.&lt;br /&gt;&lt;br /&gt;Другое возможное применение — отправка кому-то сообщения по расписанию. Например, при помощи такой команды:&lt;br /&gt;&lt;pre&gt;echo "gajim-remote send_chat_message user@example.com 'Hello'" | at 10:00&lt;/pre&gt;Ровно в 10:00 пользователю будет отправлено сообщение «Hello» (если, конечно, Gajim будет в этот момент запущен).&lt;br /&gt;&lt;br /&gt;Итак, даже этот небольшой набор команд в сочетании с инструментами командной строки позволяет сделать что-то полезное.&lt;br /&gt;&lt;br /&gt;Если работа gajim-remote покажется слишком медленной, можно воспользоваться, например, командой dbus-send или qdbus для отправки сообщения напрямую через D-Bus.&lt;br /&gt;&lt;br /&gt;Список предоставляемых функций можно посмотреть при помощи команды&lt;br /&gt;&lt;pre&gt;qdbus org.gajim.dbus /org/gajim/dbus/RemoteObject&lt;/pre&gt;Вызвать же функцию можно так:&lt;br /&gt;&lt;pre&gt;qdbus org.gajim.dbus /org/gajim/dbus/RemoteObject toggle_roster_appearance&lt;/pre&gt;Работает намного быстрее gajim-remote, но приходится явно указывать, кому мы шлём команды.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4154333943174084921-6648849086084415891?l=strange-to-say.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/Tj3i9GaXp0N4OxtzK7Jj-B2paU4/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Tj3i9GaXp0N4OxtzK7Jj-B2paU4/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/Tj3i9GaXp0N4OxtzK7Jj-B2paU4/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Tj3i9GaXp0N4OxtzK7Jj-B2paU4/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/zKMV/~4/oOX0ulxiNdg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://strange-to-say.blogspot.com/feeds/6648849086084415891/comments/default" title="Комментарии к сообщению" /><link rel="replies" type="text/html" href="http://strange-to-say.blogspot.com/2009/07/gajim.html#comment-form" title="Комментарии: 0" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4154333943174084921/posts/default/6648849086084415891?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4154333943174084921/posts/default/6648849086084415891?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/zKMV/~3/oOX0ulxiNdg/gajim.html" title="Управляем Gajim из командной строки" /><author><name>Вадим</name><uri>http://www.blogger.com/profile/03928284652612977325</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="30" height="32" src="http://1.bp.blogspot.com/_hRyhd7EUrGc/Sk5VleynHlI/AAAAAAAAAfE/ucW5wDwhBPw/S220/my_avatar.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://strange-to-say.blogspot.com/2009/07/gajim.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DU8GRHs6fCp7ImA9WxFWGEs.&quot;"><id>tag:blogger.com,1999:blog-4154333943174084921.post-7584374994125762711</id><published>2009-07-20T18:49:00.019+03:00</published><updated>2010-06-07T02:43:45.514+03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-06-07T02:43:45.514+03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="математика" /><category scheme="http://www.blogger.com/atom/ns#" term="утилиты" /><title>Построение графиков с помощью PyXPlot</title><content type="html">Утилит, позволяющих построить на компьютере график какой-то функции, превеликое множество. Но не каждая способна создать график в достойном качестве, и с соответствующим оформлением. Многие из них интерактивны, но часто это мешает, когда нужно менять много параметров графика. Поэтому при активной работе с графиками часто применяются командные «графопостроители» — фактически маленькие языки программирования.&lt;br /&gt;&lt;br /&gt;Среди программ таких можно отметить, например, asymptote, популярный gnuplot, metapost и другие. Достойное место в этом ряду занимает &lt;a href="http://www.pyxplot.org.uk/"&gt;PyXPlot&lt;/a&gt; (её команды, кстати, во многом совпадают с командами gnuplot, так что изучив одну из этих программ, легко разобраться в другой). Отличительными особенностями программы являются простота и высокое качество результата. Ей и посвящен этот обзор.&lt;br /&gt;&lt;span class='fullpost'&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Запуск программы&lt;/span&gt;&lt;br /&gt;PyXPlot есть в дистрибутиве Ubuntu и Debian, так что установка должна пройти без проблем. В крайнем случае, всегда можно скачать программу с родного сайта.&lt;br /&gt;&lt;br /&gt;Сразу нужно отметить, что PyXPlot — программа чисто консольная. Работать с ней можно как интерактивно, вводя команду за командой, так и в скриптовом режиме. В последнем случае команды записываются в отдельный файл, который затем «скармливается» PyXPlot.&lt;br /&gt;&lt;br /&gt;Запускается PyXPlot как обычно:&lt;br /&gt;&lt;pre&gt;pyxplot СКРИПТЫ&lt;/pre&gt;&lt;br /&gt;Если вместо списка файлов поставить дефис, то программа будет читать команды со стандартного ввода, что очень удобно при автоматизации. Например, так можно нарисовать синусоиду:&lt;br /&gt;&lt;pre&gt;echo 'plot sin(x)' | pyxplot -&lt;/pre&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_hRyhd7EUrGc/SmSr1rm-p-I/AAAAAAAAAfo/KGEmSl0zEIM/s1600-h/pyxplot.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 274px; height: 174px;" src="http://3.bp.blogspot.com/_hRyhd7EUrGc/SmSr1rm-p-I/AAAAAAAAAfo/KGEmSl0zEIM/s320/pyxplot.png" alt="" id="BLOGGER_PHOTO_ID_5360598395205363682" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Простейшие операции&lt;/span&gt;&lt;br /&gt;Главная команда для рисования графиков — plot. Она позволяет не только рисовать графики функции, но и строить «по точкам» графики данных, записанных в файл.&lt;br /&gt;&lt;br /&gt;Чтобы построить данные из файла, нужно просто указать его имя в апострофах или двойных кавычках после команды plot. Данные в файле должны быть обычным текстом с одним или несколькими столбцами чисел, разделенных пробелами или запятыми. Если имя заканчивается на «.gz», он будет автоматически распакован перед построением.&lt;br /&gt;&lt;pre&gt;plot 'data.gz'&lt;/pre&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_hRyhd7EUrGc/SmS9B7cmYdI/AAAAAAAAAf4/bTUal63Z_z4/s1600-h/pyxplot.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 256px; height: 173px;" src="http://4.bp.blogspot.com/_hRyhd7EUrGc/SmS9B7cmYdI/AAAAAAAAAf4/bTUal63Z_z4/s320/pyxplot.png" alt="" id="BLOGGER_PHOTO_ID_5360617297312899538" border="0" /&gt;&lt;/a&gt;Так как в файле указаны отдельные значения, то и отображаются они по отдельности, маркерами.&lt;br /&gt;&lt;br /&gt;По умолчанию результаты сохраняются в файл «pyxplot.eps».&lt;br /&gt;&lt;br /&gt;Построения графика функции полностью аналогична. Нужно просто записать её после команды plot. В качестве аргумента нужно использовать x.&lt;br /&gt;&lt;pre&gt;plot sin(x)/x&lt;/pre&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_hRyhd7EUrGc/SmS-sOr6b5I/AAAAAAAAAgA/3EOZ2IPZvCc/s1600-h/pyxplot.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 274px; height: 174px;" src="http://1.bp.blogspot.com/_hRyhd7EUrGc/SmS-sOr6b5I/AAAAAAAAAgA/3EOZ2IPZvCc/s320/pyxplot.png" alt="" id="BLOGGER_PHOTO_ID_5360619123543535506" border="0" /&gt;&lt;/a&gt;Можно построить сразу несколько графиков в одной системе координат, просто перечислив функции (или имена файлов) через запятую.&lt;br /&gt;&lt;pre&gt;plot sin(x)/x, sin(x)&lt;/pre&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_hRyhd7EUrGc/SmTAbxms66I/AAAAAAAAAgI/3TFSypwKcak/s1600-h/pyxplot.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 274px; height: 174px;" src="http://2.bp.blogspot.com/_hRyhd7EUrGc/SmTAbxms66I/AAAAAAAAAgI/3TFSypwKcak/s320/pyxplot.png" alt="" id="BLOGGER_PHOTO_ID_5360621039882398626" border="0" /&gt;&lt;/a&gt;&lt;span style="font-size:130%;"&gt;Переменные и функции&lt;/span&gt;&lt;br /&gt;В теле файла с командами можно объявить переменные и пользовательские функции при помощи операции «=». Всё достаточно интуитивно:&lt;br /&gt;&lt;pre&gt;a = 2&lt;br /&gt;b = 3&lt;br /&gt;plot sqrt(a*pow(x,2) + b)&lt;/pre&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_hRyhd7EUrGc/SmTBeFHBtBI/AAAAAAAAAgQ/PbOiNI65U4w/s1600-h/pyxplot.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 264px; height: 174px;" src="http://4.bp.blogspot.com/_hRyhd7EUrGc/SmTBeFHBtBI/AAAAAAAAAgQ/PbOiNI65U4w/s320/pyxplot.png" alt="" id="BLOGGER_PHOTO_ID_5360622178989618194" border="0" /&gt;&lt;/a&gt;В PyXPlot встроены самые распространенные математические функции, такие как: sin, cos, tan, exp, min, log, acos, asin, atan, sqrt, pow и т. д.&lt;br /&gt;&lt;pre&gt;f(x) = sqrt(x)*sin(x)&lt;br /&gt;plot f(x)&lt;/pre&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_hRyhd7EUrGc/SmTCxuwE5UI/AAAAAAAAAgY/XN2HyB85_e8/s1600-h/pyxplot.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 263px; height: 173px;" src="http://1.bp.blogspot.com/_hRyhd7EUrGc/SmTCxuwE5UI/AAAAAAAAAgY/XN2HyB85_e8/s320/pyxplot.png" alt="" id="BLOGGER_PHOTO_ID_5360623616096789826" border="0" /&gt;&lt;/a&gt;&lt;span style="font-size:130%;"&gt;Настройки графика&lt;/span&gt;&lt;br /&gt;При помощи команды set можно задать дополнительные параметры графика, такие как подписи осей (x label и ylabel) и заголовок графика (title). В подписях можно использовать формат формулы в формате TeX (их нужно обязательно заключить в знаки «$»). Использование TeX делает график намного симпатичнее и презентабельнее.&lt;br /&gt;&lt;br /&gt;Пример:&lt;br /&gt;&lt;pre&gt;set xlabel '$x$'&lt;br /&gt;set ylabel '$y$'&lt;br /&gt;set title 'Plot of $\sin(x)\over x$'&lt;br /&gt;plot sin(x)/x&lt;/pre&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_hRyhd7EUrGc/SmTGWuIa0uI/AAAAAAAAAgg/2I6oD8Nq5eI/s1600-h/pyxplot.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 278px; height: 194px;" src="http://3.bp.blogspot.com/_hRyhd7EUrGc/SmTGWuIa0uI/AAAAAAAAAgg/2I6oD8Nq5eI/s320/pyxplot.png" alt="" id="BLOGGER_PHOTO_ID_5360627550120497890" border="0" /&gt;&lt;/a&gt;Можно также задать имя выходного файла (set output) и формат выходных данных (set terminal). Поддерживаются распространённые форматы: postscript, pdf, png, jpeg.&lt;br /&gt;&lt;br /&gt;Пример:&lt;br /&gt;&lt;pre&gt;set terminal png&lt;br /&gt;set output 'plot.png'&lt;br /&gt;plot cos(x)*exp(x)&lt;/pre&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_hRyhd7EUrGc/SmTH_QoTO6I/AAAAAAAAAgw/FPAOdpAi3S8/s1600-h/plot.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 191px;" src="http://3.bp.blogspot.com/_hRyhd7EUrGc/SmTH_QoTO6I/AAAAAAAAAgw/FPAOdpAi3S8/s320/plot.png" alt="" id="BLOGGER_PHOTO_ID_5360629346087418786" border="0" /&gt;&lt;/a&gt;&lt;span style="font-size:130%;"&gt;Работа с файлами данных&lt;/span&gt;&lt;br /&gt;Данные в файле можно использовать как независимые координаты при построении. Для этого нужно добавить парметр using к команде plot.&lt;br /&gt;&lt;br /&gt;Например, команда&lt;br /&gt;&lt;pre&gt;plot 'data.gz' using 1:2&lt;/pre&gt;строит график, используя первый столбец как координату x точек, а второй — как координату y.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Стили графика&lt;/span&gt;&lt;br /&gt;Стиль построения графика настраивается при помощи параметра with.&lt;br /&gt;&lt;br /&gt;Команда&lt;br /&gt;&lt;pre&gt;plot 'data.gz' with points&lt;/pre&gt;строит точечный график, а команда&lt;br /&gt;&lt;pre&gt;plot 'data.gz' with lines&lt;/pre&gt;соединяет точки отрезками.&lt;br /&gt;&lt;br /&gt;Можно также откладывать ошибку на графике (with yerrorbars), но для этого потребуется третий столбец.&lt;br /&gt;&lt;br /&gt;Тип маркеров и линий также настраивается при помощи модификаторов pointtype и linetype. Подробности — в документации.&lt;br /&gt;&lt;pre&gt;plot sin(x) with lines linetype 3&lt;/pre&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_hRyhd7EUrGc/SmTMpV2yP4I/AAAAAAAAAg4/3MNI6KfJulA/s1600-h/pyxplot.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 274px; height: 174px;" src="http://2.bp.blogspot.com/_hRyhd7EUrGc/SmTMpV2yP4I/AAAAAAAAAg4/3MNI6KfJulA/s320/pyxplot.png" alt="" id="BLOGGER_PHOTO_ID_5360634467091365762" border="0" /&gt;&lt;/a&gt;&lt;span style="font-size:130%;"&gt;Диапазоны по осям&lt;/span&gt;&lt;br /&gt;При построении можно указать размеры осей. Для этого нужно указать минимально и максимальное значения по каждой из осей в квадратных скобках через двоеточие. Если нужно указать параметры только для одной оси, то для другой просто записсывается «[:]» без чисел. Пример:&lt;br /&gt;&lt;pre&gt;plot [-1:1][-1:1] sin(x)&lt;/pre&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_hRyhd7EUrGc/SmTOuCrJzGI/AAAAAAAAAhA/SHpPsegKbJI/s1600-h/pyxplot.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 272px; height: 174px;" src="http://4.bp.blogspot.com/_hRyhd7EUrGc/SmTOuCrJzGI/AAAAAAAAAhA/SHpPsegKbJI/s320/pyxplot.png" alt="" id="BLOGGER_PHOTO_ID_5360636746864905314" border="0" /&gt;&lt;/a&gt;&lt;span style="font-size:130%;"&gt;Заключение&lt;/span&gt;&lt;br /&gt;Разумеется, возможности программы не исчерпываются только перечисленными командами. Утилита имеет ещё очень много разных возможностей: от аппроксимации данных из файла до построения графиков векторных полей.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://pyxplot.org.uk/examples/04mc/02fft/output.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 648px; height: 333px;" src="http://pyxplot.org.uk/examples/04mc/02fft/output.png" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://pyxplot.org.uk/examples/01pf/05vortex/output.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 390px; height: 255px;" src="http://pyxplot.org.uk/examples/01pf/05vortex/output.png" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4154333943174084921-7584374994125762711?l=strange-to-say.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/2S4os-Gr3Tez2wGPLmufk9aFuQM/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/2S4os-Gr3Tez2wGPLmufk9aFuQM/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/2S4os-Gr3Tez2wGPLmufk9aFuQM/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/2S4os-Gr3Tez2wGPLmufk9aFuQM/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/zKMV/~4/PIziB-HUmj8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://strange-to-say.blogspot.com/feeds/7584374994125762711/comments/default" title="Комментарии к сообщению" /><link rel="replies" type="text/html" href="http://strange-to-say.blogspot.com/2009/07/pyxplot.html#comment-form" title="Комментарии: 0" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4154333943174084921/posts/default/7584374994125762711?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4154333943174084921/posts/default/7584374994125762711?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/zKMV/~3/PIziB-HUmj8/pyxplot.html" title="Построение графиков с помощью PyXPlot" /><author><name>Вадим</name><uri>http://www.blogger.com/profile/03928284652612977325</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="30" height="32" src="http://1.bp.blogspot.com/_hRyhd7EUrGc/Sk5VleynHlI/AAAAAAAAAfE/ucW5wDwhBPw/S220/my_avatar.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_hRyhd7EUrGc/SmSr1rm-p-I/AAAAAAAAAfo/KGEmSl0zEIM/s72-c/pyxplot.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://strange-to-say.blogspot.com/2009/07/pyxplot.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkYEQno5fyp7ImA9WxNTGUo.&quot;"><id>tag:blogger.com,1999:blog-4154333943174084921.post-3666012915388885249</id><published>2009-07-20T11:53:00.014+03:00</published><updated>2009-08-22T22:41:43.427+03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-08-22T22:41:43.427+03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="linux" /><category scheme="http://www.blogger.com/atom/ns#" term="регулярные выражения" /><category scheme="http://www.blogger.com/atom/ns#" term="утилиты" /><title>Массовое переименование файлов</title><content type="html">Наверное, каждый сталкивался с ситуацией, когда нужно переименовать по какому-то шаблону огромное количество файлов. Например, поменять в названиях песен имя исполнителя и заголовок. Или вставить определенную дату в название группы фотографий.&lt;br /&gt;&lt;br /&gt;В этих случаях на помощь приходят регулярные выражения и специальные утилиты для массового переименования.&lt;br /&gt;&lt;span class="fullpost"&gt;&lt;br /&gt;Для меня наиболее удобна консольная утилита prename (или rename), входящая в состав пакета perl. Но кому-то больше по душе, наверное, придутся программы с графическим интерфейсом. Могу посоветовать программы krename или gprename. Однако, в большинстве случаев вполне хватит и prename.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Введение&lt;/span&gt;&lt;br /&gt;Синтаксис команды выглядит очень просто:&lt;br /&gt;&lt;pre&gt;prename ШАБЛОН ФАЙЛЫ&lt;/pre&gt;&lt;br /&gt;Но за этой простотой скрывается огромная мощь. Дело в том, что в качестве шаблона используются &lt;a rel="nofollow" href="http://ru.wikipedia.org/wiki/%D0%A0%D0%B5%D0%B3%D1%83%D0%BB%D1%8F%D1%80%D0%BD%D1%8B%D0%B5_%D0%B2%D1%8B%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F"&gt;регулярные выражения&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Параметр ФАЙЛЫ может быть как списком файлов, так и шаблоном в стиле bash, использующим «*» для любой последовательности символов и «?» для одиночного символа. Например, «*.txt» — это все файлы с раширением «txt».&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Регулярные выражения&lt;/span&gt;&lt;br /&gt;Остановимся поподробнее на регулярных выражениях. Это настолько обширная тема, что о них пишутся целые книги. И настолько сложная, что большую популярность получила известная шутка: «Некоторые люди, когда сталкиваются с какой-то проблемой, думают: “Думаю, я применю регулярные выражения.” Теперь у них две проблемы.» (Jamie Zawinski) Однако, в простых случаях регулярные выражения просты и удобны. Разве что выглядят непривычно. (Честно говоря, иногда они выглядят так, будто по клавиатуре пробежала кошка.)&lt;br /&gt;&lt;br /&gt;В утилите prename регулярные выражения обычно имеют следующий вид:&lt;br /&gt;&lt;pre&gt;s/ИСХОДНЫЙ/КОНЕЧНЫЙ/&lt;/pre&gt;ИСХОДНЫЙ и КОНЕЧНЫЙ — это шаблоны. Первый задает подстроку, которую нужно найти в имени, а второй — на что эту подстроку заменить.&lt;br /&gt;&lt;br /&gt;В простейшем случае это могут быть обычные слова. Команда&lt;br /&gt;&lt;pre&gt;prename 's/Алиса/Боб/' *.txt&lt;/pre&gt;заменит во всех файлах с расширением «txt» слово «Алиса» на слово «Боб».&lt;br /&gt;&lt;br /&gt;Нужно заметить, что шаблон применяется к каждому имени файла только один раз. То есть файл с именем «Эх, Алиса, Алиса.txt» будет заменен на «Эх, Боб, Алиса.txt». Чтобы шаблон примянялся столько, сколько нужно, необходимо добавить параметр g к регулярному выражению:&lt;br /&gt;&lt;pre&gt;prename 's/Алиса/Боб/g' *.txt&lt;/pre&gt;&lt;span style="font-size:130%;"&gt;Подстановки&lt;/span&gt;&lt;br /&gt;Кроме собственно слов можно использовать специальные подстановочные символы:&lt;br /&gt;«&lt;b&gt;.&lt;/b&gt;» — любой одиночный символ,&lt;br /&gt;«&lt;b&gt;\d&lt;/b&gt;» — цифра,&lt;br /&gt;«&lt;b&gt;\D&lt;/b&gt;» — любой символ кроме цифры,&lt;br /&gt;«&lt;b&gt;\w&lt;/b&gt;» — буква, цифра или знак подчёркивания,&lt;br /&gt;«&lt;b&gt;\W&lt;/b&gt;» — всё, кроме букв, цифр и знака подчёркивания,&lt;br /&gt;«&lt;b&gt;\s&lt;/b&gt;» — любой пробельный символ,&lt;br /&gt;«&lt;b&gt;\S&lt;/b&gt;» — любой непробельный символ.&lt;br /&gt;&lt;br /&gt;Например, команда&lt;br /&gt;&lt;pre&gt;prename 's/\s/_/g' *.txt&lt;/pre&gt;заменит пробелы на знаки подчёркивания. Несколько идущих подряд пробелов будут заменены на несколько подчёркиваний.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Начало и конец&lt;/span&gt;&lt;br /&gt;Есть также специальные псевдосиволы:&lt;br /&gt;«&lt;b&gt;^&lt;/b&gt;» — обозначает начало слова,&lt;br /&gt;«&lt;b&gt;$&lt;/b&gt;» — обозначает конец слова.&lt;br /&gt;&lt;br /&gt;Например, команда&lt;br /&gt;&lt;pre&gt;prename 's/a$/b/' *.txt&lt;/pre&gt;заменит «a» на «b» только если «a» — последний символ имени файла.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Экранирование&lt;/span&gt;&lt;br /&gt;Если же какой-то из специальных символов нужно использовать в шаблоне как символ обычный, его нужно экранировать обратным слэшем. Например, «.» — одиночный символ, «\.» — просто точка.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Повторы&lt;/span&gt;&lt;br /&gt;После любой части регулярного выражения можно поставить количество его повторов:&lt;br /&gt;«&lt;b&gt;?&lt;/b&gt;» — ноль или один,&lt;br /&gt;«&lt;b&gt;*&lt;/b&gt;» — ноль и более,&lt;br /&gt;«&lt;b&gt;+&lt;/b&gt;» — один и более,&lt;br /&gt;«&lt;b&gt;{n}&lt;/b&gt;» — ровно n&lt;br /&gt;«&lt;b&gt;{m,n}&lt;/b&gt;» — от m до n,&lt;br /&gt;«&lt;b&gt;{m,}&lt;/b&gt;» — от m и более,&lt;br /&gt;«&lt;b&gt;{,n}&lt;/b&gt;» — от нуля до n.&lt;br /&gt;&lt;br /&gt;Символы «?», «+» и «*» по умолчанию являются «жадными», то есть пытаются отхватить как можно большую часть выражения, попадающую под шаблон.&lt;br /&gt;&lt;br /&gt;Команда&lt;br /&gt;&lt;pre&gt;prename 's/\s+/_/g' *.txt&lt;/pre&gt;заменит пробелы на знаки подчёркивания. Несколько идущих подряд пробелов будут заменены на одно подчёркивание.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Группировка и ссылки&lt;/span&gt;&lt;br /&gt;Части выражения можно группировать при помощи круглых скобок. Также можно ссылаться на скобки при помощи выражения вида «$номер». Здесь — номер — это номер пары скобок в порядке их вхождения в выражение.&lt;br /&gt;&lt;br /&gt;Например, команда&lt;br /&gt;&lt;pre&gt;prename 's/(\d)+/$1/g' *.txt&lt;/pre&gt;заменит несколько подряд идущих одинаковых цифр в имени на одну (эту же!) цифру. То есть файл с именем «11122233333.txt» будет переименован в «123.txt».&lt;br /&gt;&lt;br /&gt;А команда&lt;br /&gt;&lt;pre&gt;prename 's/(.*) - (.*)\.mp3/$2 - $1\.mp3/' *.mp3&lt;/pre&gt;переименует файл «Ария Филиппа - Шаляпин.mp3» в «Шаляпин - Ария Филиппа.mp3».&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Что за там, за горизонтом?&lt;/span&gt;&lt;br /&gt;Есть также полезная возможность заглянуть вперед или назад, но не включая определенную часть шаблона в найденное:&lt;br /&gt;«&lt;b&gt;(?=ШАБЛОН)&lt;/b&gt;» — просмотр вперёд,&lt;br /&gt;«&lt;b&gt;(?!ШАБЛОН)&lt;/b&gt;» — просмотр вперёд (с отрицанием),&lt;br /&gt;«&lt;b&gt;(?&amp;lt;=ШАБЛОН)&lt;/b&gt;» — просмотр назад,&lt;br /&gt;«&lt;b&gt;(?&amp;lt;!ШАБЛОН)&lt;/b&gt;» — просмотр назад (с отрицанием).&lt;br /&gt;&lt;br /&gt;Например, команда&lt;br /&gt;&lt;pre&gt;prename 's/(?&amp;lt;!x)a/b/g' *.txt&lt;/pre&gt;заменит «a» на «b» в файлах с раширением «txt» только если «a» не идёт после x.&lt;br /&gt;&lt;br /&gt;А команда&lt;br /&gt;&lt;pre&gt;prename 's/a(?!x)/b/g' *.txt&lt;/pre&gt;заменит «a» на «b» в файлах с раширением «txt» только если «a» не идёт перед x.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Заключение&lt;/span&gt;&lt;br /&gt;Регулярные выражения имеют огромную область применения. Естественно, в этом посте перечислены далеко не все их возможности. Например, не сказано про транслитерацию или диапазоны символов.&lt;br /&gt;&lt;br /&gt;В качестве неплохого руководства по ним могу порекомендовать книгу Дж. Фридла «Регулярные выражения».&lt;br /&gt;&lt;br /&gt;У утилиты, конечно, есть и недостатки. Главный очевиден — нужно знать регулярные выражения. Есть и другие. Например, с помощью prename нельзя пронумеровать файлы.&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4154333943174084921-3666012915388885249?l=strange-to-say.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/9z2xa-Og2LAzALYL15ubfvJPS-8/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/9z2xa-Og2LAzALYL15ubfvJPS-8/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/9z2xa-Og2LAzALYL15ubfvJPS-8/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/9z2xa-Og2LAzALYL15ubfvJPS-8/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/zKMV/~4/x4NTzoOsfEM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://strange-to-say.blogspot.com/feeds/3666012915388885249/comments/default" title="Комментарии к сообщению" /><link rel="replies" type="text/html" href="http://strange-to-say.blogspot.com/2009/07/blog-post_20.html#comment-form" title="Комментарии: 2" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4154333943174084921/posts/default/3666012915388885249?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4154333943174084921/posts/default/3666012915388885249?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/zKMV/~3/x4NTzoOsfEM/blog-post_20.html" title="Массовое переименование файлов" /><author><name>Вадим</name><uri>http://www.blogger.com/profile/03928284652612977325</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="30" height="32" src="http://1.bp.blogspot.com/_hRyhd7EUrGc/Sk5VleynHlI/AAAAAAAAAfE/ucW5wDwhBPw/S220/my_avatar.gif" /></author><thr:total>2</thr:total><feedburner:origLink>http://strange-to-say.blogspot.com/2009/07/blog-post_20.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUYBRHczeSp7ImA9WxNUEEo.&quot;"><id>tag:blogger.com,1999:blog-4154333943174084921.post-4709925307621607577</id><published>2009-07-17T13:20:00.008+03:00</published><updated>2009-11-01T12:59:15.981+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-11-01T12:59:15.981+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="GNOME" /><category scheme="http://www.blogger.com/atom/ns#" term="linux" /><title>Идеи для GNOME Shell</title><content type="html">Как известно, сейчас полным ходом идет работа над GNOME 3, в котором привычный интерфейс будет заменен на GNOME Shell. И хотя последний будет включен в GNOME 2.28, работа сейчас находится на достаточно ранней стадии. В связи с этим разработчики предлагают каждому предложить свою идею, каким должен быть интерфейс нового GNOME. Сбор идей производится на &lt;a href="http://live.gnome.org/GnomeShell/DesignerPlayground"&gt;сайте проекта&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Вот, некоторые из предложений, представленных на сайте, которые мне показались достаточно любопытными (подробности — на сайте GNOME).&lt;br /&gt;&lt;br /&gt;&lt;span class=fullpost&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;&lt;/span&gt;&lt;span style="font-size:130%;"&gt;Расширенный вид меню&lt;/span&gt;&lt;br /&gt;Máirín Duffy предлагает сделать возможность отображения в меню Activities не только приложений, но и связаной с ними информации. Например, недавно открытых файлов.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.ubuntu-pics.de/bild/18981/appmenu_app_with_currently_open_windows_9zP1Iw.png" target="_blank"&gt;&lt;img src="http://www.ubuntu-pics.de/thumb/18981/appmenu_app_with_currently_open_windows_9zP1Iw.png" border="0" /&gt;&lt;/a&gt; &lt;a href="http://www.ubuntu-pics.de/bild/18982/appmenu_chat_app_recent_convos_4ZLMhb.png" target="_blank"&gt;&lt;img src="http://www.ubuntu-pics.de/thumb/18982/appmenu_chat_app_recent_convos_4ZLMhb.png" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.ubuntu-pics.de/bild/18984/appmenu_creativeapp_recent_files_GO0Jjo.png" target="_blank"&gt;&lt;img src="http://www.ubuntu-pics.de/thumb/18984/appmenu_creativeapp_recent_files_GO0Jjo.png" border="0" /&gt;&lt;/a&gt; &lt;a href="http://www.ubuntu-pics.de/bild/18985/appmenu_creativeapps_flatlist_Ebzv21.png" target="_blank"&gt;&lt;img src="http://www.ubuntu-pics.de/thumb/18985/appmenu_creativeapps_flatlist_Ebzv21.png" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Мини-терминал&lt;/span&gt;&lt;br /&gt;Предлагается также сделать небольшое поле для ввода команд. Может быть полезным, если приложению требуются какие-то параметры для запуска.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.ubuntu-pics.de/bild/18987/overlay_mode_mini_terminal_view_modes_0daQjc.png" target="_blank"&gt;&lt;img src="http://www.ubuntu-pics.de/thumb/18987/overlay_mode_mini_terminal_view_modes_0daQjc.png" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Полка для окон&lt;/span&gt;&lt;br /&gt;Довольно интересной представляется возможность складывать неиспользуемые окна на «полку». Особенно удобно это будет с устройствами, оборудованными тачскринами. Тогда окна можно будет просто выделить при помощи «лассо» и свернуть, чтобы не занимали место.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.ubuntu-pics.de/bild/18988/3450460435_53ec08c9ed_o_T06mA1.png" target="_blank"&gt;&lt;img src="http://www.ubuntu-pics.de/thumb/18988/3450460435_53ec08c9ed_o_T06mA1.png" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;«Связывание» окон&lt;/span&gt;&lt;br /&gt;Если эта возможность будет реализована, то пользователь сможет «связывать» два окна, после чего они будут отображаться как единое целое. Шаг в сторону тайловых оконных менеджеров.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.ubuntu-pics.de/bild/18989/3450460435_53ec08c9ed_o_X474d7.png" target="_blank"&gt;&lt;img src="http://www.ubuntu-pics.de/thumb/18989/3450460435_53ec08c9ed_o_X474d7.png" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Отображение приложений справа&lt;/span&gt;&lt;br /&gt;Некоторые пользователи считают, что список приложений лучше выводить справа от миниатюр рабочих столов. Выглядит достаточно непривычно.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.ubuntu-pics.de/bild/18990/3450460435_53ec08c9ed_o_1r491w.png" target="_blank"&gt;&lt;img src="http://www.ubuntu-pics.de/thumb/18990/3450460435_53ec08c9ed_o_1r491w.png" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Цепочка последних действий&lt;/span&gt;&lt;br /&gt;Очень удобным мне показалось отображение последних открытых документов и приложений рядом с меню Activities.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.ubuntu-pics.de/bild/18992/3450460435_53ec08c9ed_o_wZ1kBM.png" target="_blank"&gt;&lt;img src="http://www.ubuntu-pics.de/thumb/18992/3450460435_53ec08c9ed_o_wZ1kBM.png" border="0" /&gt;&lt;/a&gt; &lt;a href="http://www.ubuntu-pics.de/bild/18994/shell_mockup_sanderqd_20090413_02_JuKy3Y.png" target="_blank"&gt;&lt;img src="http://www.ubuntu-pics.de/thumb/18994/shell_mockup_sanderqd_20090413_02_JuKy3Y.png" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.ubuntu-pics.de/bild/18993/drop_down_menu_20090504_rXUJsZ.png" target="_blank"&gt;&lt;img src="http://www.ubuntu-pics.de/thumb/18993/drop_down_menu_20090504_rXUJsZ.png" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Заголовки окон вместо панели&lt;/span&gt;&lt;br /&gt;Не знаю, насколько это удобно, но есть предложение отказаться от панели, где отображались бы запущенные приложения. Вместо этого можно было бы использовать заголовки окон.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.ubuntu-pics.de/bild/18995/windowtraysmockup_2GSX2g.png" target="_blank"&gt;&lt;img src="http://www.ubuntu-pics.de/thumb/18995/windowtraysmockup_2GSX2g.png" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Умные окна&lt;/span&gt;&lt;br /&gt;Предлагается позволить окнам самим мледить за тем, кто из них на переднем плане. Возможно,что это позволит переключаться между ними, затрачивая меньше времени. Хотя выглядит тоже очень очень непривычно. По-моему, окнам лучше быть просто окнами.&lt;br /&gt;&lt;br /&gt;&lt;object height="385" width="480"&gt;&lt;param name="movie" value="http://www.youtube.com/v/lsZvwyxJ9vk&amp;amp;hl=ru&amp;amp;fs=1&amp;amp;"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;embed src="http://www.youtube.com/v/lsZvwyxJ9vk&amp;amp;hl=ru&amp;amp;fs=1&amp;amp;" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" height="385" width="480"&gt;&lt;/embed&gt;&lt;a class="hlregmasowpqcxeiygjc" href="http://www.youtube.com/v/lsZvwyxJ9vk&amp;amp;hl=ru&amp;amp;fs=1&amp;amp;"&gt;&lt;/a&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Категории в меню&lt;/span&gt;&lt;br /&gt;Некоторые идеи выглядят очень инновационо. Например, отображение всех приложений и документов в одном меню. Поэтому появилось предложение сделать возможность выбора между новым и старым стилем представления.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.ubuntu-pics.de/bild/18997/overlay_flat_list_mockup_48Epqo.png" target="_blank"&gt;&lt;img src="http://www.ubuntu-pics.de/thumb/18997/overlay_flat_list_mockup_48Epqo.png" border="0" /&gt;&lt;/a&gt; &lt;a href="http://www.ubuntu-pics.de/bild/18998/overlay_categories_mockup_LO6KQ2.png" target="_blank"&gt;&lt;img src="http://www.ubuntu-pics.de/thumb/18998/overlay_categories_mockup_LO6KQ2.png" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Выпадающий список приложений&lt;/span&gt;&lt;br /&gt;В то время как одни хотят избавиться от панели задач, другие предлагают менее радикальное решение — представить запущенные приложения в виде списка.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.ubuntu-pics.de/bild/18999/windows_needing_attention_concept_19A7VT.jpg" target="_blank"&gt;&lt;img src="http://www.ubuntu-pics.de/thumb/18999/windows_needing_attention_concept_19A7VT.jpg" border="0" /&gt;&lt;/a&gt; &lt;a href="http://www.ubuntu-pics.de/bild/19000/2_NwhLLu.jpg" target="_blank"&gt;&lt;img src="http://www.ubuntu-pics.de/thumb/19000/2_NwhLLu.jpg" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Отказ от списка приложений&lt;/span&gt;&lt;br /&gt;Есть также идея вообще отказаться от списка приложений в пользу списка контактов и документов (организованного, например, при помощи Zeitgeist). В целом, довольно здравая мысль, так как всё равно люди часто используют приложения только для обработки документов или для свзяи с кем-то.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.ubuntu-pics.de/bild/19003/documents2_TgK7Cc.png" target="_blank"&gt;&lt;img src="http://www.ubuntu-pics.de/thumb/19003/documents2_TgK7Cc.png" border="0" /&gt;&lt;/a&gt; &lt;a href="http://www.ubuntu-pics.de/bild/19004/people2_0j1uqU.png" target="_blank"&gt;&lt;img src="http://www.ubuntu-pics.de/thumb/19004/people2_0j1uqU.png" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Контакты в Activities&lt;/span&gt;&lt;br /&gt;Также кроме простого отображения списка контактов можно выводить и дополнительную информацию, получая более тесную интеграцию окружения рабочего стола с мессенджерами.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.ubuntu-pics.de/bild/19005/gnome_shell_people_overlay_mockup_t7rZVK.png" target="_blank"&gt;&lt;img src="http://www.ubuntu-pics.de/thumb/19005/gnome_shell_people_overlay_mockup_t7rZVK.png" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Вот, вкратце, наиболее инновационные предложения. Есть какая-то идея? Присоединяйтесь и вы!&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4154333943174084921-4709925307621607577?l=strange-to-say.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/Ael8lc6pv2T4CFU9RmAt1X2u93Y/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Ael8lc6pv2T4CFU9RmAt1X2u93Y/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/Ael8lc6pv2T4CFU9RmAt1X2u93Y/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Ael8lc6pv2T4CFU9RmAt1X2u93Y/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/zKMV/~4/nCS2TYfJF_I" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://strange-to-say.blogspot.com/feeds/4709925307621607577/comments/default" title="Комментарии к сообщению" /><link rel="replies" type="text/html" href="http://strange-to-say.blogspot.com/2009/07/gnome-shell.html#comment-form" title="Комментарии: 0" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4154333943174084921/posts/default/4709925307621607577?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4154333943174084921/posts/default/4709925307621607577?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/zKMV/~3/nCS2TYfJF_I/gnome-shell.html" title="Идеи для GNOME Shell" /><author><name>Вадим</name><uri>http://www.blogger.com/profile/03928284652612977325</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="30" height="32" src="http://1.bp.blogspot.com/_hRyhd7EUrGc/Sk5VleynHlI/AAAAAAAAAfE/ucW5wDwhBPw/S220/my_avatar.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://strange-to-say.blogspot.com/2009/07/gnome-shell.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A04CRHs_fip7ImA9WxJbEEo.&quot;"><id>tag:blogger.com,1999:blog-4154333943174084921.post-7911511324542384039</id><published>2009-07-16T20:58:00.008+03:00</published><updated>2009-07-20T11:52:45.546+03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-07-20T11:52:45.546+03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="программирование" /><category scheme="http://www.blogger.com/atom/ns#" term="linux" /><category scheme="http://www.blogger.com/atom/ns#" term="python" /><category scheme="http://www.blogger.com/atom/ns#" term="утилиты" /><title>Информация о медиафайлах</title><content type="html">В недавнем посте об отображении тегов mp3-файлов рассказывалось об утилите mp3info. К сожалению, она обладает существенными недостатками: не понимает ID3v2 и работает, как следует из названия, только с mp3-файлам.&lt;br /&gt;&lt;br /&gt;Однако, сама по себе утилитка довольно удобна. Поэтому я решил написать небольшой скрипт, предоставляющий похожий интерфейс, но понимающий большее количество медиаформатов.&lt;br /&gt;&lt;span class=fullpost&gt;&lt;br /&gt;Естественно, писал я его не на пустом месте. Для работы скрипта потребуется библиотека &lt;a rel="nofollow" href="http://doc.freevo.org/2.0/SourceDoc/KaaMetadata"&gt;Kaa.Metadata&lt;/a&gt;:&lt;br /&gt;&lt;pre&gt;sudo aptitude install python-kaa-metadata&lt;/pre&gt;&lt;br /&gt;Параметров у скрипта всего два (для простоты): форматная строка и файл (или несколько файлов через пробел):&lt;br /&gt;&lt;pre&gt;mediainfo.py ФОРМАТ файл(ы)&lt;/pre&gt;&lt;br /&gt;При указании файла можно использовать стандартные шаблоны. Так что вполне допустимо имя вида «*.mp3». Можно использовать и более сложные шаблоны: «~/Музыка/*/*.mp3».&lt;br /&gt;&lt;br /&gt;Скрипт не умеет рекурсивно обходить каталоги, но это ему и не нужно. Обход можно реализовать, например, средствами bash.&lt;br /&gt;&lt;br /&gt;Подробнее о форматной строке. В ней можно использовать следующие шаблоны:&lt;br /&gt;%t — название,&lt;br /&gt;%a — исполнитель,&lt;br /&gt;%r — частота дискретизации,&lt;br /&gt;%l — продолжительность,&lt;br /&gt;%m — продолжительность (только минуты),&lt;br /&gt;%s — продолжительность (только секунды)&lt;br /&gt;%c — кодек,&lt;br /&gt;%b — битрейт,&lt;br /&gt;%n — номер трека,&lt;br /&gt;%A — альбом,&lt;br /&gt;%g — жанр,&lt;br /&gt;%% — символ %.&lt;br /&gt;&lt;br /&gt;В ней также можно использовать обычные питоновские экранированные последовательности: \n, \t и т. д.&lt;br /&gt;&lt;br /&gt;Вставлять \n в конце форматной строки не нужно, это делается автоматически. Кроме того, вывод скрипта автоматически переконвертируется в кодировку текущей локали.&lt;br /&gt;&lt;br /&gt;Если теги файла записаны в однобайтовой кодировке и формат тегов не предусматривает указания кодировки, то скорее всего вместо ожидаемой cp1251 будет latin-1. Впрочем, ответственность за это лежит на библиотеке. Может, это можно настроить, я глубоко не вникал. Во всяком случае, это еще один повод перевести все теги в utf-8.&lt;br /&gt;&lt;br /&gt;Утилиту можно использовать как саму по себе, так и в конвейере:&lt;br /&gt;&lt;pre&gt;mediainfo.py '%l' ~/Музыка/*/* | awk '{s += $1} END {print "≈",int(s/3600),"hour(s)"}'&lt;/pre&gt;&lt;br /&gt;А вот, собственно, исходный текст скрипта:&lt;br /&gt;&lt;pre name='code' class='python'&gt;#!/usr/bin/env python&lt;br /&gt;#-*- coding:utf-8 -*-&lt;br /&gt;&lt;br /&gt;# Disable all warnings&lt;br /&gt;import warnings&lt;br /&gt;warnings.filterwarnings('ignore')&lt;br /&gt;&lt;br /&gt;# Disable log messages&lt;br /&gt;#import logging&lt;br /&gt;#logger = logging.getLogger('metadata')&lt;br /&gt;#logger.setLevel(logging.CRITICAL)&lt;br /&gt;&lt;br /&gt;# Get locale encoding&lt;br /&gt;import locale&lt;br /&gt;encoding = locale.getdefaultlocale()[1]&lt;br /&gt;&lt;br /&gt;import os&lt;br /&gt;import sys&lt;br /&gt;import glob&lt;br /&gt;import string&lt;br /&gt;import kaa.metadata&lt;br /&gt;&lt;br /&gt;class MyTemplate(string.Template): delimiter = '%'&lt;br /&gt;&lt;br /&gt;def addItem(infolist, info):&lt;br /&gt;    item = {}&lt;br /&gt;    item['t'] = info.title                      # Title&lt;br /&gt;    item['a'] = info.artist                     # Artist&lt;br /&gt;    item['r'] = info.samplerate                 # Samplerate&lt;br /&gt;    item['l'] = int(info.length)                # Length (seconds)&lt;br /&gt;    item['m'] = int(item['l'] / 60) % 60        # Length (minutes only)&lt;br /&gt;    item['s'] = format(item['l'] % 60, '02d')   # Length (seconds only)&lt;br /&gt;    item['c'] = info.codec                      # Codec&lt;br /&gt;    item['b'] = info.bitrate                    # Bitrate&lt;br /&gt;    item['n'] = info.trackno                    # Track number&lt;br /&gt;    item['A'] = info.album                      # Album title&lt;br /&gt;    item['g'] = info.genre                      # Genre&lt;br /&gt;    infolist.append(item)&lt;br /&gt;&lt;br /&gt;def process(path):&lt;br /&gt;    infolist = []&lt;br /&gt;    path = os.path.normpath(path)&lt;br /&gt;    for f in glob.glob(os.path.expanduser(path)):&lt;br /&gt;        if os.path.isdir(f):&lt;br /&gt;            continue&lt;br /&gt;        try:&lt;br /&gt;            info = kaa.metadata.parse(f)&lt;br /&gt;        except:&lt;br /&gt;            info = None&lt;br /&gt;        if info != None:&lt;br /&gt;            addItem(infolist, info)&lt;br /&gt;    return infolist&lt;br /&gt;&lt;br /&gt;if len(sys.argv) &lt; 3:&lt;br /&gt;    print 'Usage:'&lt;br /&gt;    print os.path.split(sys.argv[0])[1], 'FORMAT file(s)'&lt;br /&gt;    exit(0)    &lt;br /&gt;for f in sys.argv[2:]:&lt;br /&gt;    infolist = process(f)        &lt;br /&gt;    for item in infolist:&lt;br /&gt;        sys.stdout.write(MyTemplate(sys.argv[1]).safe_substitute(item).encode(encoding) + '\n')&lt;/pre&gt;&lt;br /&gt;Не забываем разрешить его выполнение:&lt;br /&gt;&lt;pre&gt;chmod +x mediainfo.py&lt;/pre&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4154333943174084921-7911511324542384039?l=strange-to-say.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/oT0q_WIZRnFttups8XCISp9IBp0/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/oT0q_WIZRnFttups8XCISp9IBp0/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/oT0q_WIZRnFttups8XCISp9IBp0/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/oT0q_WIZRnFttups8XCISp9IBp0/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/zKMV/~4/87Ju_kMRjHM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://strange-to-say.blogspot.com/feeds/7911511324542384039/comments/default" title="Комментарии к сообщению" /><link rel="replies" type="text/html" href="http://strange-to-say.blogspot.com/2009/07/mp3-mp3info.html#comment-form" title="Комментарии: 0" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4154333943174084921/posts/default/7911511324542384039?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4154333943174084921/posts/default/7911511324542384039?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/zKMV/~3/87Ju_kMRjHM/mp3-mp3info.html" title="Информация о медиафайлах" /><author><name>Вадим</name><uri>http://www.blogger.com/profile/03928284652612977325</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="30" height="32" src="http://1.bp.blogspot.com/_hRyhd7EUrGc/Sk5VleynHlI/AAAAAAAAAfE/ucW5wDwhBPw/S220/my_avatar.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://strange-to-say.blogspot.com/2009/07/mp3-mp3info.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A04HRHc7eip7ImA9WxJbEEo.&quot;"><id>tag:blogger.com,1999:blog-4154333943174084921.post-2531429219684325114</id><published>2009-07-15T15:47:00.010+03:00</published><updated>2009-07-20T11:52:15.902+03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-07-20T11:52:15.902+03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="linux" /><category scheme="http://www.blogger.com/atom/ns#" term="утилиты" /><title>Информация об mp3-файлах</title><content type="html">Иногда, когда залезаешь в свою коллекцию музыки, возникает необходимость составить список песен с продолжительностью. Например, для того, чтобы распечатать и приложить к диску.&lt;br /&gt;&lt;br /&gt;Для того, чтобы получить названия песен можно использовать ls, но не всегда название файла соответствует содержимому. И ещё реже в названии указана продолжительность.&lt;br /&gt;&lt;br /&gt;В этом случае на помощь приходит пакет mp3info.&lt;br /&gt;&lt;span class=fullpost&gt;&lt;br /&gt;В Ubuntu устанавливается как обычно:&lt;br /&gt;&lt;pre name='code' class='bash'&gt;&lt;br /&gt;sudo aptitude install mp3info&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;У него довольно много возможностей по редактированию и отображению тегов. Подробности можно узнать в man. Для того, чтобы получить список песен в альбоме можно воспользоваться следующей командой:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;mp3info -p 'ФОРМАТ' *.mp3&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Она выведет данные об mp3-файлах в текущем каталоге в соответствии со строкой ФОРМАТ.&lt;br /&gt;&lt;br /&gt;В форматной строке можно использовать как обычные символы (они выведутся как есть), так и специальные шаблоны. Вот список некоторых из них:&lt;br /&gt;%f — имя файла без пути,&lt;br /&gt;%F — имя файла с путём,&lt;br /&gt;%k — размер файла в килобайтах,&lt;br /&gt;%a — исполнитель,&lt;br /&gt;%g — жанр,&lt;br /&gt;%l — альбом,&lt;br /&gt;%n — номер трека,&lt;br /&gt;%t — название трека,&lt;br /&gt;%y — год,&lt;br /&gt;%q — частота сэмплирования (в кГц),&lt;br /&gt;%r — битрейт,&lt;br /&gt;%m — продолжительность (только минуты),&lt;br /&gt;%s — продолжительность (только секунды),&lt;br /&gt;%% — знак процента,&lt;br /&gt;\n — перевод строки,&lt;br /&gt;\t — горизонтальная табуляция,&lt;br /&gt;\\ — обратный слэш.&lt;br /&gt;&lt;br /&gt;Например, команда&lt;br /&gt;&lt;pre&gt;mp3info -p '%n. %a - %t (%m:%s)\n' *.mp3&lt;/pre&gt;&lt;br /&gt;выведет на экран что-то вроде:&lt;br /&gt;&lt;blockquote&gt;01. Allison Crowe - It Came Upon the Midnight Clea (0:42) &lt;br /&gt;02. Allison Crowe - Silent Night (4:2) &lt;br /&gt;03. Allison Crowe - In the Bleak Midwinter (4:3) &lt;br /&gt;04. Allison Crowe - What Child Is This (4:4) &lt;br /&gt;05. Allison Crowe - The First Noel (5:34) &lt;br /&gt;06. Allison Crowe - O Holy Night (4:16) &lt;/blockquote&gt;&lt;br /&gt;При работе с файлами, содержащими теги на русском языке могут возникнуть проблемы. Дело в том, что в них данные очень часто записываются в виндососвской кодировке cp1251. Решить проблему можно перекодировав вывод команды при помощи утилиты iconv:&lt;br /&gt;&lt;br /&gt;Просто по старой виндузячьей традиции теги хранятся в кодировке cp1251. Я все перекодирую при помощи easytag, но если файлик с такими тегами попался, то можно использовать iconv. Например, так:&lt;br /&gt;&lt;pre&gt;mp3info -p '%a - %t \n'  *.mp3 |iconv -f cp1251&lt;/pre&gt;&lt;br /&gt;Следует помнить, что mp3info работает только с тегами ID3v1.1.&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4154333943174084921-2531429219684325114?l=strange-to-say.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/4Hn3AqC2INFdO0Igxj6XEekREyw/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/4Hn3AqC2INFdO0Igxj6XEekREyw/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/4Hn3AqC2INFdO0Igxj6XEekREyw/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/4Hn3AqC2INFdO0Igxj6XEekREyw/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/zKMV/~4/6B2CepTG-wE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://strange-to-say.blogspot.com/feeds/2531429219684325114/comments/default" title="Комментарии к сообщению" /><link rel="replies" type="text/html" href="http://strange-to-say.blogspot.com/2009/07/mp3.html#comment-form" title="Комментарии: 0" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4154333943174084921/posts/default/2531429219684325114?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4154333943174084921/posts/default/2531429219684325114?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/zKMV/~3/6B2CepTG-wE/mp3.html" title="Информация об mp3-файлах" /><author><name>Вадим</name><uri>http://www.blogger.com/profile/03928284652612977325</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="30" height="32" src="http://1.bp.blogspot.com/_hRyhd7EUrGc/Sk5VleynHlI/AAAAAAAAAfE/ucW5wDwhBPw/S220/my_avatar.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://strange-to-say.blogspot.com/2009/07/mp3.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0MCSH08cSp7ImA9WxJUGUk.&quot;"><id>tag:blogger.com,1999:blog-4154333943174084921.post-6371896629128644776</id><published>2009-07-13T09:10:00.034+03:00</published><updated>2009-07-18T23:37:49.379+03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-07-18T23:37:49.379+03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="программирование" /><category scheme="http://www.blogger.com/atom/ns#" term="звук" /><category scheme="http://www.blogger.com/atom/ns#" term="C++" /><title>Пишем пищалку для будильника</title><content type="html">Часто мне не хватает удобного и простого будильника под Linux. Органайзеры со всплывающими окошками и проигрыванием заданной мелодии явно избыточны для того, чтобы просто не забыть про чайник. А старый добрый beep я использовать не могу по причине отсутствия PC-Speaker. Можно бы, конечно, поискать подходящую программу, но проще написать её самому. Тем более, программирование звука — это просто!&lt;br /&gt;&lt;span class=fullpost&gt;&lt;br /&gt;Итак, что должна уметь делать программа? Во-первых, издавать какой-то звук. Причем используя для этого звуковую карту. А во-вторых, должна быть консольной с возможностью указания времени звучания в командной строке.&lt;br /&gt;&lt;br /&gt;Чтобы проигать какой-то звук я решил использовать библиотеку &lt;a href="http://xiph.org/ao/"&gt;libao&lt;/a&gt; — очень простую в использовании и удобную. При этом ещё и кроссплатформенную. К слову, она поддерживает ALSA, ESD, OSS, Pulse, чего должно хватить с головой.&lt;br /&gt;&lt;br /&gt;На родном сайте есть ссылки для скачивания и подробная документация. Пользователи Debian/Ubuntu могут установить библиотеку обычным способом&lt;br /&gt;&lt;pre name="code" class="bash"&gt;&lt;br /&gt;sudo aptitude install libao2&lt;br /&gt;sudo aptitude install libao-dev&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Пакет libao2 — это сама библиотека, он нужен будет для работы программы, а libao-dev — это заголовочные файлы.&lt;br /&gt;&lt;br /&gt;Библиотека написана на чистом C, поэтому для удобства можно обернуть все необходимые функции в класс¸ а потом, если потребуется, выделить в отдельную библиотеку. Удобство может показаться сомнительным, но лично мне в основной программе не хочется вводить посторонние переменные и писать функции для открытия/закрытия устройства. Да и забыть могу. А так всё, что нужно, прописано в конструкторе и деструкторе, а значит вызывается само собой.&lt;br /&gt;&lt;br /&gt;Работу с библиотекой можно разбить на три этапа:&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;инициализация, настройка формата вывода, открытие устройства;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;воспроизведение звука;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;закрытие устройства и завершение работы с библиотекой.&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;Класс можно написать, например, такой:&lt;br /&gt;&lt;pre name="code" class="cpp"&gt;&lt;br /&gt;class Beeper {&lt;br /&gt;  private:&lt;br /&gt;  ao_device *device;&lt;br /&gt;  int driver;&lt;br /&gt;  ao_sample_format format;&lt;br /&gt;&lt;br /&gt;  public:&lt;br /&gt;  Beeper();&lt;br /&gt;  void operator() (double freq, double time, double volume = 0.75);&lt;br /&gt;  ~Beeper();&lt;br /&gt;};&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;С конструктором и деструктором всё понятно, а вот перегруженная операция вызова функции — это и есть метод класса, который издает звуки. Ему передается всего три параметра: freq — частота звучания в герцах, time — время звучания в секундах, volume — громкость (от 0.0 до 1.0).&lt;br /&gt;&lt;br /&gt;Про инициализацию и завершение работы с библиотекой можно почитать в документации. Скажу лишь про то, как, собственно, издавать звуки. Тут потребуется вспомнить школьный курс физики, в котором говориться, что звук — это просто колебания воздуха.&lt;br /&gt;&lt;br /&gt;Можно взять синусоиду, тогда мы получим чистый тон. Частота колебаний определяет высоту звука, а амплитуда — громкость. Тут всё просто. На практике же мы сталкиваемся со следующей проблемой: компьютер-то работает не с математическими формулами, а с числами.&lt;br /&gt;&lt;br /&gt;Но и тут проблема легко решается. Звуковая карта получает на вход последовательность чисел, задающих амплитуду через некоторые малые промежутки времени. Количество таких отсчетов амплитуды в секунду называется частотой дискретизации. Типичное значение — это 44100 Гц. Почему именно такое число? Дело в том, что человек может слышать звуки с частотой не выше ≈20000 Гц. А по теореме Котельникова, чтобы точно передать сигнал с какой-то частотой, нужна минимум в два раза большая частота дискретизации. Хотя, для низких звуков такая высокая частота — излишество.&lt;br /&gt;&lt;br /&gt;Другие важные параметры — это разрядность и количество каналов (моно, стерео).&lt;br /&gt;&lt;br /&gt;Разрядность говорит, сколько бит тратится на один отсчет амплитуды. Чем больше разрядность, тем точнее передается звук. Но для обычных нужд хватит и 16 бит, то бишь двух байт. Тут возникает такой вопрос: а как хранить эти два байта? Сначала старший или младший? Это &lt;a href="http://ru.wikipedia.org/wiki/%C3%90%C2%9F%C3%90%C2%BE%C3%91%C2%80%C3%91%C2%8F%C3%90%C2%B4%C3%90%C2%BE%C3%90%C2%BA_%C3%90%C2%B1%C3%90%C2%B0%C3%90%C2%B9%C3%91%C2%82%C3%90%C2%BE%C3%90%C2%B2"&gt;старая компьютерная проблема&lt;/a&gt;. Я же решил не заморачиваться и сначала помещаю младший байт, а потом старший (так называемый little-endian порядок байтов). Для указания, что используется именно такой параметр, соответствующему полю структуры, отвечающей за формат сигнала присваивается значение AO_FMT_LITTLE.&lt;br /&gt;&lt;br /&gt;Разбить двубайтовой целое на два однобайтовых легко. Для этого можно использовать побитовое И с числом 0xFF. Это даст младщий байт, так как старшие биты будут умножены на 0. А потом можно сдвинуть все старшие биты в исходном числе на 8 бит влево и повторить процедуру.&lt;br /&gt;&lt;br /&gt;Для 16 битного звука значения амплитуды должны быть в диапазоне от -32768 до 32767. Эти крайние величины соответствуют максимальной громкости. Если нужен звук потише, то амплитуду можно уменьшить. Амплитуда, равная 0 — это тишина.&lt;br /&gt;&lt;br /&gt;Если мы хотим выводить звук в несколько каналов, то значения амплитуды для каждого из них чередуются.&lt;br /&gt;&lt;br /&gt;Итак, как издать звук. Для этого в памяти создается буфер, чтоб не отправлять каждый байт поодиночке. Буфер должен иметь размер t×F×b, где t — это время звучания, F — частота дискретизации, а b — разрядность в байтах. Потом мы в цикле записываем значения синусоиды с нужной частотой и амплитудой. А затем всё это дело выводится на устройство. Подробности можно посмотреть в коде программы.&lt;br /&gt;&lt;br /&gt;Когда класс готов, можно заняться самой пищалкой. В ней просто несколько раз повторяется звук  с частотой 880 Гц (это ля второй октавы) и длительностью 0,3 с. Пауза между звукам — 0,2 с. По умолчанию сигнал повторяется 20 раз (то есть 20/(0,3+0,2)=10 с), но можно передать нужную дительность как параметр командной строки.&lt;br /&gt;&lt;br /&gt;Как видно, работа с классом очень проста и функция main выглядит ясной и чистой.&lt;br /&gt;&lt;br /&gt;После того, как программа скомпилирована, её можно поместить, например, в /usr/local/bin или создать deb-пакет, чтоб потом можно было поделиться с друзьями.&lt;br /&gt;&lt;br /&gt;Использовать её просто. Например, нужно подать сигнал в 12:30, а исполняемый файл называется beep. Тогда пишем следующее:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;echo "beep" | at 12:30&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Если beep лежит в домашней папке, то не забываем указать путь:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;echo "~/beep" | at 12:30&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;У at очень гибкий формат указания времени исполнения, так что рекомендую заглянуть в man.&lt;br /&gt;&lt;br /&gt;Можно также всё это оформить в виде скрипта:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#!/bin/sh&lt;br /&gt;echo "~/beep" | at $@&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;$@ — это специальная переменная, хранящая параметры, переданные скрипту. Так что можно будет просто написать, например:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;alarm.sh 12:30&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;А вот вся программа в одном файле.&lt;br /&gt;&lt;pre name="code" class="cpp"&gt;&lt;br /&gt;#include &amp;lt;ao/ao.h&amp;gt;&lt;br /&gt;#include &amp;lt;cmath&amp;gt;&lt;br /&gt;#include &amp;lt;cstdlib&amp;gt;&lt;br /&gt;&lt;br /&gt;#define BITS       16&lt;br /&gt;#define CHANNELS   1&lt;br /&gt;#define RATE       22050&lt;br /&gt;&lt;br /&gt;class Beeper {&lt;br /&gt;private:&lt;br /&gt;ao_device *device;&lt;br /&gt;int driver;&lt;br /&gt;ao_sample_format format;&lt;br /&gt;&lt;br /&gt;public:&lt;br /&gt;Beeper() {&lt;br /&gt; ao_initialize();&lt;br /&gt; this-&amp;gt;driver = ao_default_driver_id();&lt;br /&gt;&lt;br /&gt; this-&amp;gt;format.bits = BITS;&lt;br /&gt; this-&amp;gt;format.channels = CHANNELS;&lt;br /&gt; this-&amp;gt;format.rate = RATE;&lt;br /&gt; this-&amp;gt;format.byte_format = AO_FMT_LITTLE;&lt;br /&gt;&lt;br /&gt; this-&amp;gt;device = ao_open_live(driver, &amp;amp;format, NULL);&lt;br /&gt; if (this-&amp;gt;device == NULL)&lt;br /&gt;     exit(1);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;void operator() (double freq, double time, double volume = 0.75) {&lt;br /&gt; int buf_size = static_cast&amp;lt;int&amp;gt;(this-&amp;gt;format.bits/8 * this-&amp;gt;format.channels * this-&amp;gt;format.rate * time);&lt;br /&gt; char *buffer = new char[buf_size];&lt;br /&gt; int sample;&lt;br /&gt;&lt;br /&gt; for (int i = 0; i &amp;lt; this-&amp;gt;format.rate * time; i++) {&lt;br /&gt;     for (int c = 0; c &amp;lt; this-&amp;gt;format.channels; c++) {&lt;br /&gt;         sample = static_cast&amp;lt;int&amp;gt;(volume * (1&amp;lt;&amp;lt;(this-&amp;gt;format.bits - 1)) * sin(2 * M_PI * freq * ((float) i/format.rate)));&lt;br /&gt;         for (int j = 0; j &amp;lt; this-&amp;gt;format.bits/8; j++) {&lt;br /&gt;             buffer[this-&amp;gt;format.bits/8*i*this-&amp;gt;format.channels + this-&amp;gt;format.channels*c + j] = sample &amp;amp; 0xff;&lt;br /&gt;             sample &amp;gt;&amp;gt;= 8;&lt;br /&gt;         }&lt;br /&gt;     }&lt;br /&gt; }&lt;br /&gt; ao_play(device, buffer, buf_size);&lt;br /&gt; delete[] buffer;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;~Beeper() {&lt;br /&gt; ao_close(device);&lt;br /&gt; ao_shutdown();&lt;br /&gt;}&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;int main(int argc, char **argv)&lt;br /&gt;{&lt;br /&gt;Beeper b;&lt;br /&gt;&lt;br /&gt;int count = (argc == 1) ? 20 : atoi(argv[1]);&lt;br /&gt;&lt;br /&gt;for (int i=0; i &amp;lt; count*2; i++){&lt;br /&gt; b(880.0, 0.3);&lt;br /&gt; b(0.0, 0.2);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;return 0;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Компилируется командой&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;g++ -lao -o beep beep.cpp&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Вот, вкратце всё. Не забываем покритиковать! ;)&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4154333943174084921-6371896629128644776?l=strange-to-say.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/deAxhKJ-R0FJx11UdzTkzRiXszk/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/deAxhKJ-R0FJx11UdzTkzRiXszk/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/deAxhKJ-R0FJx11UdzTkzRiXszk/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/deAxhKJ-R0FJx11UdzTkzRiXszk/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/zKMV/~4/2Rg9dSeIElk" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://strange-to-say.blogspot.com/feeds/6371896629128644776/comments/default" title="Комментарии к сообщению" /><link rel="replies" type="text/html" href="http://strange-to-say.blogspot.com/2009/07/blog-post.html#comment-form" title="Комментарии: 2" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4154333943174084921/posts/default/6371896629128644776?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4154333943174084921/posts/default/6371896629128644776?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/zKMV/~3/2Rg9dSeIElk/blog-post.html" title="Пишем пищалку для будильника" /><author><name>Вадим</name><uri>http://www.blogger.com/profile/03928284652612977325</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="30" height="32" src="http://1.bp.blogspot.com/_hRyhd7EUrGc/Sk5VleynHlI/AAAAAAAAAfE/ucW5wDwhBPw/S220/my_avatar.gif" /></author><thr:total>2</thr:total><feedburner:origLink>http://strange-to-say.blogspot.com/2009/07/blog-post.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0IEQXwyfSp7ImA9WxJUGUk.&quot;"><id>tag:blogger.com,1999:blog-4154333943174084921.post-2575905393194774640</id><published>2009-05-06T00:07:00.007+03:00</published><updated>2009-07-18T23:38:20.295+03:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-07-18T23:38:20.295+03:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="linux" /><title>Ввод специальных символов или «типографские раскладки»</title><content type="html">Наверняка многие пользователи хотели бы вводить различные специальные символы вроде кавычек-ёлочек («») или длинного тире (—) простыми сочетаниями клавиш, но не знают как. И остается им облизываться на &lt;a rel="nofollow" href="http://ilyabirman.ru/typography-layout/"&gt;раскладку Бирмана&lt;/a&gt;, для которой в Windows есть удобный установочный пакет. Либо копаться по форумам и выполнять загадочные действия: что-то скачивать, что-то где-то править в здоровенном xml-файле. А то и вовсе использовать старую добрую таблицу символов.&lt;br /&gt;&lt;br /&gt;Однако, всё что нужно, уже может быть в вашем дистрибутиве!&lt;br /&gt;&lt;span class=fullpost&gt;&lt;br /&gt;Дело в том, что существуют специальные клавиатурные раскладки, позволяющие вводить спецсимволы при помощи нажатия особой клавиши одновременно с какой-то из обычных клавиш клавиатуры. Например, после нажатия правого Alt и &gt; получается знак ». Всё просто и легко запоминается (» похожа на &gt;). Такие раскладки и называются типографскими.&lt;br /&gt;&lt;br /&gt;К сожалению, я сейчас использую только Ubuntu 9.04 и не могу сказать, верно ли сказанное в других дистрибутивах.&lt;br /&gt;&lt;br /&gt;В старых версиях для того, чтобы использовать все возможности и удобства расширенной раскладки, мне пришлось (по совету с какого-то сайта) править несколько файлов со списками раскладок, что неудобно, да и неправильно, так как эти файлы принадлежали пакету xkb-data.&lt;br /&gt;&lt;br /&gt;После установки Ubuntu 9.04, я хотел было уже опять искать в сети способ включить типографскую раскладку, но тут случайно обнаружил, что всё уже есть в самой системе. Достаточно лишь зайти в настройки клавиатуры («Система» → «Параметры» → «Клавиатура» → вкладка «Раскладки» → «Параметры раскладки») и включить соответствующую галочку.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.ubuntu-pics.de/bild/18877/screenshot_001_wkviec_i6Jecr.png" target="_blank"&gt;&lt;img src="http://www.ubuntu-pics.de/thumb/18877/screenshot_001_wkviec_i6Jecr.png" border="0" alt="Настройка раскладки" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Теперь пару слов о том, как же теперь эти символы вводить. В качестве «волшебной клавиши» для ввода по умолчанию используется правый Alt, но это можно изменить в том же окне в разделе «Key to choose 3rd level».&lt;br /&gt;&lt;br /&gt;Раскладка, конечно не такая богатая, как некоторые другие, но всё, что нужно позволяет легко вводить. Вот несколько полезных сочетаний:&lt;br /&gt;&lt;br /&gt;Alt-&gt; »&lt;br /&gt;Alt-&lt; «&lt;br /&gt;Alt-- —&lt;br /&gt;Alt-. …&lt;br /&gt;&lt;br /&gt;Остальные можно посмотреть, распечатав раскладку в том же окне настроек клавиатуры.&lt;br /&gt;&lt;a href="http://www.ubuntu-pics.de/bild/18878/screenshot002x_2Nl6Qp.png" target="_blank"&gt;&lt;img src="http://www.ubuntu-pics.de/thumb/18878/screenshot002x_2Nl6Qp.png" border="0" alt="Русская раскладка со спецсимволами" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Несколько слов для тех, кто не хочет или не может пользоваться гномовским клавиатурным настройщиком. Активировать расширенные раскладки можно командой setxbmap. Пример того, как это сделать, я подсмотрел на сайте Сергея Столярова.&lt;br /&gt;&lt;pre&gt;setxkbmap -option grp:caps_toggle -option grp_led:caps -layout us+typo,ru:2+typo&lt;/pre&gt;&lt;br /&gt;Эта команда задаёт способ переключения (grp:capstoggle, т.е. клавишей Caps Lock), индикатор, используемый для отображения раскладки (grpled:caps, т.е. индикатор Caps Lock), а также непосредственно раскладки (us+typo и ru:2+typo). Как можно заметить, слой с дополнительными символами добавляется к обеим раскладкам (us и ru).&lt;br /&gt;&lt;br /&gt;Если вы используете другой способ настройки XKB, то вы должны там заменить us на us+typo и ru на ru:2+typo.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Upd.&lt;/b&gt; Я забыл упомянуть (спасибо пользователю &lt;a rel="nofollow" href="http://welinux.ru/user/konkere"&gt;konkere&lt;/a&gt; за подсказку) о другом, даже более мощном штатном способе ввода спецсимволов — &lt;a rel="nofollow" href="http://ru.wikipedia.org/wiki/Compose"&gt;клавише Compose&lt;/a&gt;. О нём довольно много написано в интернете, поэтому отсылаю читателя к википедии и гуглу. Скажу лишь о некоторых недостатках этого способа.&lt;br /&gt;&lt;br /&gt;Чтобы ввести сочетание Compose + &gt; + &gt; нужно переключаться в английскую раскладку, так как в русской нет символа &gt;. (Имеется в виду обычная русская раскладка, которую можно видеть на клавиатуре. Расширенная русская позволяет вводить как &lt; и &gt; — Alt-Shift-б и Alt-Shift-б — так и квадратные и круглые скобки без дополнительных переключений.) Можно, конечно, использовать ~/.XCompose, что было бы очень удобно, так как позволяет создавать свои раскладки, но в гномовских приложениях используется другой метод ввода и файл с настройками просто проигнорируется.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Upd. 2&lt;/b&gt; Ещё рекомендую включить опцию «Unicode additions».&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.ubuntu-pics.de/bild/18879/screenshot_001_r4v2nv_nOg5yA.png" target="_blank"&gt;&lt;img src="http://www.ubuntu-pics.de/thumb/18879/screenshot_001_r4v2nv_nOg5yA.png" border="0" alt="Включение Unicode additions" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Тогда можно будет указанным выше способом вводить при помощи цифровой клавиатуры стрелки (←→⇐⇒) и некоторые математические операторы (⋅×÷).&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Upd. 3&lt;/b&gt; Пользователь &lt;a rel="nofollow" href="http://welinux.ru/user/pluton"&gt;pluton&lt;/a&gt; натолкнул меня на мысль об еще одном способе ввода символов — по их коду в Unicode. Для этого нужно нажать Ctrl-Shift-U. Появится маленькая подчеркнутая буква &lt;u&gt;u&lt;/u&gt;, после которой нужно ввести 16-ричный код символа и нажать пробел. К сожалению, использовать этот способ для ввода текстов в Firefox не получится, так как там это сочетание клавиш, по-видимому, уже используется для отображения исходного кода посещённой страницы. Но в текстовых редакторах (например в gedit) этот способ может пригодиться (если, конечно, вы помните все коды Unicode ;)).&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4154333943174084921-2575905393194774640?l=strange-to-say.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/MoESCXZc6JnGI3VxnFGjParTN2I/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/MoESCXZc6JnGI3VxnFGjParTN2I/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/MoESCXZc6JnGI3VxnFGjParTN2I/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/MoESCXZc6JnGI3VxnFGjParTN2I/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/blogspot/zKMV/~4/R7CCdQIHV2U" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://strange-to-say.blogspot.com/feeds/2575905393194774640/comments/default" title="Комментарии к сообщению" /><link rel="replies" type="text/html" href="http://strange-to-say.blogspot.com/2009/05/blog-post.html#comment-form" title="Комментарии: 0" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4154333943174084921/posts/default/2575905393194774640?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4154333943174084921/posts/default/2575905393194774640?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/blogspot/zKMV/~3/R7CCdQIHV2U/blog-post.html" title="Ввод специальных символов или «типографские раскладки»" /><author><name>Вадим</name><uri>http://www.blogger.com/profile/03928284652612977325</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="30" height="32" src="http://1.bp.blogspot.com/_hRyhd7EUrGc/Sk5VleynHlI/AAAAAAAAAfE/ucW5wDwhBPw/S220/my_avatar.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://strange-to-say.blogspot.com/2009/05/blog-post.html</feedburner:origLink></entry></feed>

