<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Do Know Evil - A Blog by Tyler Mulligan &#187; Programming</title>
	<atom:link href="http://www.doknowevil.net/category/computers/software/programming/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.doknowevil.net</link>
	<description>Tips and Tricks About Computers, Web Development, Linux, the Internet and the Like</description>
	<lastBuildDate>Thu, 29 Jul 2010 03:37:42 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Python Multi-head X (Nvidia TwinView / Dual Monitor) Development Notes</title>
		<link>http://www.doknowevil.net/2010/07/05/python-multi-head-x-nvidia-twinview-dual-monitor-development-notes/</link>
		<comments>http://www.doknowevil.net/2010/07/05/python-multi-head-x-nvidia-twinview-dual-monitor-development-notes/#comments</comments>
		<pubDate>Mon, 05 Jul 2010 23:29:24 +0000</pubDate>
		<dc:creator>Tyler Mulligan</dc:creator>
				<category><![CDATA[Application Management]]></category>
		<category><![CDATA[Computers]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Operating Systems]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://www.doknowevil.net/?p=745</guid>
		<description><![CDATA[Preface The following development notes were written after researching the underlying handling of dual monitors in the X window system on Linux. I&#8217;ve included a code snippet that I built to help demonstrate behavior and create a proof of concept to show I can determine which monitor a window is on using only python and]]></description>
			<content:encoded><![CDATA[<h2>Preface</h2>
<p>The following development notes were written after researching the underlying handling of dual monitors in the <a href="http://en.wikipedia.org/wiki/X_Window_System" target="_blank">X window system</a> on Linux. I&#8217;ve included a code snippet that I built to help demonstrate behavior and create a proof of concept to show I can determine which monitor a window is on using only python and no statically set coordinates.  </p>
<h2>Introduction</h2>
<p>I mentioned in my previous post that I&#8217;m using an nVidia video card with &#8220;<a href="http://www.nvidia.com/object/feature_twinview.html" target="_blank">TwinView</a>&#8221; software that outputs my video as if it were one screen, which it technically is, one X screen.  This means that the distinction between monitors is not mapped in the X tree, it&#8217;s handled by the window manager. Unlike <a href="http://en.wikipedia.org/wiki/Xinerama" target="_blank">Xinerama</a>, which has an x session per monitor and stitches them together.  Xinerama, however, has is being deprecated in favor of <a href="http://en.wikipedia.org/wiki/RandR" target="_blank">RandR</a> but regardless, TwinView is my choice and is not an option for me to change to.</p>
<p>With all of that said, the decision to bridge python to c that interfaces with compiz is a deadend and would be better implemented based on the new 0.9.0 C++ api.  It would be nice to be able to return a list of windows from a &#8220;monitor&#8221; object.  However, that&#8217;s beyond my current scope.  I was able to whip up some python that to show that implementing the monitor management in python using the gtk module isn&#8217;t /that/ hacky.  I emphasize because I read some posts that claimed window decorations could be an issue in accurate calculations.</p>
<h2>Some Code</h2>
<p>Read the comment on line 2.  <a href="http://www.pygtk.org/docs/pygtk/" target="_blank">Learn more about pygtk here</a></p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"><span class="co1">#!/usr/bin/python</span>
<span class="co1"># Print some information about the X environment, the monitor setup, currently active window and cursor position</span>
<span class="kw1">import</span> gtk.<span class="me1">gdk</span>
&nbsp;
screen = gtk.<span class="me1">gdk</span>.<span class="me1">screen_get_default</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
<span class="kw1">print</span> <span class="st0">&quot;X default screen size: %d x %d&quot;</span> <span class="sy0">%</span> <span class="br0">&#40;</span>screen.<span class="me1">get_width</span><span class="br0">&#40;</span><span class="br0">&#41;</span>, screen.<span class="me1">get_height</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
<span class="kw1">print</span> <span class="st0">&quot;xid of root window: %d&quot;</span> <span class="sy0">%</span> screen.<span class="me1">get_root_window</span><span class="br0">&#40;</span><span class="br0">&#41;</span>.<span class="me1">xid</span>
&nbsp;
monitors = <span class="kw2">int</span><span class="br0">&#40;</span>screen.<span class="me1">get_n_monitors</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
<span class="kw1">print</span> <span class="st0">&quot;== %d monitors ==&quot;</span> <span class="sy0">%</span> monitors
<span class="kw1">for</span> m <span class="kw1">in</span> <span class="kw2">range</span><span class="br0">&#40;</span><span class="nu0">0</span>, monitors<span class="br0">&#41;</span>:
    <span class="kw1">print</span> <span class="st0">&quot; - geometry of monitor %d: %s&quot;</span> <span class="sy0">%</span> <span class="br0">&#40;</span>m, screen.<span class="me1">get_monitor_geometry</span><span class="br0">&#40;</span>m<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp;
window = screen.<span class="me1">get_active_window</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
win_x, win_y, win_w, win_h, win_bit_depth = window.<span class="me1">get_geometry</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
<span class="kw1">print</span> <span class="st0">&quot;active window on monitor: %d&quot;</span> <span class="sy0">%</span> screen.<span class="me1">get_monitor_at_point</span><span class="br0">&#40;</span><span class="br0">&#40;</span>win_x+<span class="br0">&#40;</span>win_w/<span class="nu0">2</span><span class="br0">&#41;</span><span class="br0">&#41;</span>,<span class="br0">&#40;</span>win_y+<span class="br0">&#40;</span>win_h/<span class="nu0">2</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
<span class="kw1">print</span> <span class="st0">&quot;window geometry (x,y,w,h): %d, %d, %d, %d&quot;</span> <span class="sy0">%</span> <span class="br0">&#40;</span>win_x,win_y,win_w,win_h<span class="br0">&#41;</span>
&nbsp;
display = gtk.<span class="me1">gdk</span>.<span class="me1">display_get_default</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
pointer = display.<span class="me1">get_pointer</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
<span class="kw1">print</span> <span class="st0">&quot;cursor position (x, y): %d, %d&quot;</span> <span class="sy0">%</span> <span class="br0">&#40;</span>pointer<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span>, pointer<span class="br0">&#91;</span><span class="nu0">2</span><span class="br0">&#93;</span><span class="br0">&#41;</span>
<span class="kw1">print</span> <span class="st0">&quot;cursor on monitor: %d&quot;</span> <span class="sy0">%</span> screen.<span class="me1">get_monitor_at_point</span><span class="br0">&#40;</span>pointer<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span>,pointer<span class="br0">&#91;</span><span class="nu0">2</span><span class="br0">&#93;</span><span class="br0">&#41;</span></pre></div></div>

<p>thanks to those in #compiz-dev and #python on freenode who helped me come around to create this snippet.  I hope it will help others looking to develop for multi-head setups in Linux.  Please let me know if I missed anything or did something incorrectly, this is new territory for me.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.doknowevil.net/2010/07/05/python-multi-head-x-nvidia-twinview-dual-monitor-development-notes/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Compiz 0.9.0 Released &#8211; Completely Rewritten in C++</title>
		<link>http://www.doknowevil.net/2010/07/04/compiz-0_9_0-released-completely-rewritten-in-c-plus-plus/</link>
		<comments>http://www.doknowevil.net/2010/07/04/compiz-0_9_0-released-completely-rewritten-in-c-plus-plus/#comments</comments>
		<pubDate>Mon, 05 Jul 2010 02:44:16 +0000</pubDate>
		<dc:creator>Tyler Mulligan</dc:creator>
				<category><![CDATA[Application Management]]></category>
		<category><![CDATA[Compiz]]></category>
		<category><![CDATA[Computers]]></category>
		<category><![CDATA[Desktop Mods]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Operating Systems]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[open source]]></category>

		<guid isPermaLink="false">http://www.doknowevil.net/?p=738</guid>
		<description><![CDATA[I was doing some in depth research / code hacking regarding the support of multi-headed output (dual monitors) on Linux. I won&#8217;t get into details but my video is being output to my monitors as &#8220;one screen&#8221; with a virtual distinctions handled by the window manager. Because of this, figuring out which of the monitors]]></description>
			<content:encoded><![CDATA[<p>I was doing some in depth research / code hacking regarding the support of multi-headed output (dual monitors) on Linux.  I won&#8217;t get into <a href="http://forum.compiz.org/viewtopic.php?f=89&#038;t=13362" title="managing windows across dual monitors in compiz?">details</a> but my video is being output to my monitors as &#8220;one screen&#8221; with a virtual distinctions handled by the window manager.  Because of this, figuring out which of the monitors you are on isn&#8217;t as straight forward as you might think.  Originally I was looking for a way to access the c functions in compiz through python but that point is now moot (likely for the better).</p>
<p>The <a href="http://lists.freedesktop.org/archives/compiz/2010-July/003429.html">first unstable release of the Compiz 0.9 series</a>, completely rewritten in C++.  As said, this &#8220;brings a whole new developer API, splits rendering into plugins, switches the buildsystem from automake to cmake and brings minor functionality improvements. This release represents the first developer and tester preview of what will eventually make the 0.10.x stable series. Please note that as such, it is not yet ready for general use as there are a number of known  ssues, regressions and incomplete functionality.&#8221;</p>
<p>Here is a <b>SLIGHTLY DATED</b> graph I got <a href="http://santiance.com/2009/10/compiz-code-comparison/">from Santiance.com</a>.</p>
<p><a href="http://www.doknowevil.net/wp-content/uploads/2010/07/compiz_comparison_chart.png" rel="shadowbox[post-738];player=img;"><img src="http://www.doknowevil.net/wp-content/uploads/2010/07/compiz_comparison_chart.png" alt="" title="compiz_comparison_chart" width="776" height="449" class="alignnone size-full wp-image-739" /></a></p>
<p>This is a really interesting turning point for the project and I&#8217;m glad I came across this while doing my research for multi-head handling in compiz. Knowing where the future lies could drastically change where I put my efforts in developing to support them.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.doknowevil.net/2010/07/04/compiz-0_9_0-released-completely-rewritten-in-c-plus-plus/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>New Python eBook, Much Better, Down and Dirty</title>
		<link>http://www.doknowevil.net/2010/07/01/new-python-ebook-much-better-down-and-dirty/</link>
		<comments>http://www.doknowevil.net/2010/07/01/new-python-ebook-much-better-down-and-dirty/#comments</comments>
		<pubDate>Fri, 02 Jul 2010 00:50:14 +0000</pubDate>
		<dc:creator>Tyler Mulligan</dc:creator>
				<category><![CDATA[Books]]></category>
		<category><![CDATA[Computers]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://www.doknowevil.net/?p=729</guid>
		<description><![CDATA[Some friends recommended a book that&#8217;s a quicker pace with some better programming practices. Learn Python The Hard way (or quick way ). It reads more like a walk-through tutorial / quick reference and gives you easily repeatable programming practices that will get you a stronger feel for the language. It&#8217;s probably best used in]]></description>
			<content:encoded><![CDATA[<p>Some friends recommended a book that&#8217;s a quicker pace with some better programming practices.  <a href="http://learnpythonthehardway.org/index" target="_blank">Learn Python The Hard way</a> (or quick way <img src='http://www.doknowevil.net/wp-includes/images/smilies/icon_razz.gif' alt=':-P' class='wp-smiley' /> ). It reads more like a walk-through tutorial / quick reference and gives you easily repeatable programming practices that will get you a stronger feel for the language.  It&#8217;s probably best used in combination with the <a href="http://docs.python.org/" target="_blank">Python Documentation</a>.  Also, a fair warning, <a href="http://oppugn.us/posts/1272050135.html">Dive Into Python has war declared against it</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.doknowevil.net/2010/07/01/new-python-ebook-much-better-down-and-dirty/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>scp-notifications for GNOME and Ubuntu &#8211; Expanding on My Original Python Script</title>
		<link>http://www.doknowevil.net/2010/06/26/scp-notifications-for-gnome-and-ubuntu-expanding-on-my-original-python-script/</link>
		<comments>http://www.doknowevil.net/2010/06/26/scp-notifications-for-gnome-and-ubuntu-expanding-on-my-original-python-script/#comments</comments>
		<pubDate>Sun, 27 Jun 2010 00:11:15 +0000</pubDate>
		<dc:creator>Tyler Mulligan</dc:creator>
				<category><![CDATA[Compiz]]></category>
		<category><![CDATA[Computers]]></category>
		<category><![CDATA[Desktop Mods]]></category>
		<category><![CDATA[GNOME]]></category>
		<category><![CDATA[KDE]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Operating Systems]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[The Internet]]></category>
		<category><![CDATA[Ubuntu]]></category>
		<category><![CDATA[Web Applications]]></category>
		<category><![CDATA[open source]]></category>
		<category><![CDATA[libnotify]]></category>
		<category><![CDATA[notification-daemon]]></category>
		<category><![CDATA[pynotify]]></category>

		<guid isPermaLink="false">http://www.doknowevil.net/?p=698</guid>
		<description><![CDATA[I&#8217;ve only been coding Python for ~12 hours total, so don&#8217;t expect this to be perfect. Knowing what I know about creating/testing other software and doing my best to scour through very light pynotify documentation, I&#8217;ve begun to build out this script to be more useful / portable / configurable. As the Version 0.6 indicates,]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve only been coding Python for ~12 hours total, so don&#8217;t expect this to be perfect.  Knowing what I know about creating/testing other software and doing my best to scour through very light pynotify documentation, I&#8217;ve begun to build out this script to be more useful / portable / configurable.  As the Version 0.6 indicates, I&#8217;m not quite at my goal yet and there is still more to learn to bring it up to that point.</p>
<p>I&#8217;m releasing this early on my blog just in case I caught any people yesterday who&#8217;ve been experimenting with my research / code so far.  I&#8217;ll share it on github when I evolve it just a bit more.</p>
<p><a href="http://interwebninja.com/videos/compiz-screenshot-piped-to-notification-daemon-for-upload.ogv">Video of it in Action</a></p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"><span class="co1">#!/usr/bin/env python</span>
<span class="co1">#</span>
<span class="co1"># Title: scp-notifications</span>
<span class="co1"># Author: Tyler Mulligan (tyler@detrition.net)</span>
<span class="co1"># Date: 06/26/2010</span>
<span class="co1"># Version: 0.6</span>
<span class="co1"># Description:</span>
<span class="co1"># Used in combination with an event, such as an action or cronjob, this script</span>
<span class="co1"># will scp the latest file from a folder to your server.</span>
<span class="co1">#</span>
<span class="co1"># Optionally, it can copy the url to your clipboard and/or show a popup with a</span>
<span class="co1"># link to the file after succesfully uploading</span>
<span class="co1">#</span>
<span class="co1"># Orginally developed to be piped to from compiz screenshot tool</span>
<span class="co1"># http://interwebninja.com/videos/compiz-screenshot-piped-to-notification-daemon-for-upload.ogv</span>
<span class="co1">#</span>
<span class="co1"># The MIT License</span>
<span class="co1">#</span>
<span class="co1"># Copyright (c) 2010 Tyler Mulligan</span>
<span class="co1">#</span>
<span class="co1"># Permission is hereby granted, free of charge, to any person obtaining a copy</span>
<span class="co1"># of this software and associated documentation files (the &quot;Software&quot;), to deal</span>
<span class="co1"># in the Software without restriction, including without limitation the rights</span>
<span class="co1"># to use, copy, modify, merge, publish, distribute, sublicense, and/or sell</span>
<span class="co1"># copies of the Software, and to permit persons to whom the Software is</span>
<span class="co1"># furnished to do so, subject to the following conditions:</span>
<span class="co1">#</span>
<span class="co1"># The above copyright notice and this permission notice shall be included in</span>
<span class="co1"># all copies or substantial portions of the Software.</span>
<span class="co1">#</span>
<span class="co1"># THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR</span>
<span class="co1"># IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,</span>
<span class="co1"># FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE</span>
<span class="co1"># AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER</span>
<span class="co1"># LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,</span>
<span class="co1"># OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN</span>
<span class="co1"># THE SOFTWARE</span>
<span class="co1">#</span>
&nbsp;
<span class="kw1">import</span> pygtk
pygtk.<span class="me1">require</span><span class="br0">&#40;</span><span class="st0">'2.0'</span><span class="br0">&#41;</span>
<span class="kw1">import</span> pynotify
<span class="kw1">import</span> gtk
<span class="kw1">import</span> <span class="kw3">sys</span>
<span class="kw1">import</span> <span class="kw3">os</span>
<span class="kw1">import</span> <span class="kw3">subprocess</span>
&nbsp;
<span class="co1"># Set Variables</span>
<span class="co1">#####################################</span>
<span class="kw3">user</span> = <span class="st0">&quot;user&quot;</span>
host = <span class="st0">&quot;server.com&quot;</span>
<span class="co1"># All should have trailing slashes</span>
lfolder = <span class="st0">&quot;/home/user/screenshots/&quot;</span>
hfolder = <span class="st0">&quot;/home/remote_user/screenshots/&quot;</span>
httplink = <span class="st0">&quot;http://&quot;</span>+host+<span class="st0">&quot;/screenshots/&quot;</span>
&nbsp;
&nbsp;
<span class="co1"># Display</span>
<span class="co1">#####################################</span>
t1 = <span class="nu0">5000</span> <span class="co1"># timeout for screenshot upload dialog</span>
t2 = <span class="nu0">3000</span> <span class="co1"># timeout for screenshot preview</span>
t3 = <span class="nu0">7000</span> <span class="co1"># timeout for link dialog</span>
&nbsp;
screenshot_preview = <span class="nu0">1</span> <span class="co1"># If using with the compiz screenshot plugin, you may want this</span>
popup_link = <span class="nu0">1</span> <span class="co1"># another popup</span>
copy_to_clipboard = <span class="nu0">0</span> <span class="co1"># automatically copy text to keyboard</span>
&nbsp;
<span class="co1"># Position</span>
<span class="co1">#####################################</span>
&nbsp;
<span class="co1"># Get screensize &lt; &lt; used for relative positioning</span>
display = gtk.<span class="me1">gdk</span>.<span class="me1">display_get_default</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
screen = display.<span class="me1">get_default_screen</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
x = screen.<span class="me1">get_width</span><span class="br0">&#40;</span><span class="br0">&#41;</span> - <span class="nu0">1</span>
y = screen.<span class="me1">get_height</span><span class="br0">&#40;</span><span class="br0">&#41;</span> - <span class="nu0">1</span>
&nbsp;
<span class="co1"># 0 for Automatic Placement</span>
<span class="st0">&quot;&quot;&quot;
x1 = 0
y1 = 0
x2 = 0
y2 = 0
x3 = 0
y3 = 0
&quot;&quot;&quot;</span>
<span class="co1"># Define Relative Position (assuming top-right)</span>
x1 = x-<span class="nu0">1</span>
y1 = <span class="nu0">12</span>
x2 = x1
y2 = y1 + <span class="nu0">100</span>
x3 = x-<span class="nu0">1</span>
y3 = <span class="nu0">12</span>
<span class="co1"># Define Static (1920 puts it on my second monitor)</span>
<span class="st0">&quot;&quot;&quot;
x1 = 1919
y1 = 12
x2 = x1
y2 = y1 + 100
x3 = 1920
y3 = 12
&quot;&quot;&quot;</span>
<span class="co1">#####################################</span>
&nbsp;
<span class="kw1">def</span> upload_cb<span class="br0">&#40;</span>n, action<span class="br0">&#41;</span>:
    <span class="kw1">assert</span> action == <span class="st0">&quot;upload&quot;</span> 
&nbsp;
    <span class="kw3">subprocess</span>.<span class="me1">call</span><span class="br0">&#40;</span><span class="br0">&#91;</span><span class="st0">&quot;scp&quot;</span>, <span class="kw3">os</span>.<span class="me1">path</span>.<span class="me1">join</span><span class="br0">&#40;</span>lfolder, f<span class="br0">&#41;</span>, <span class="st0">'%s@%s:%s'</span> <span class="sy0">%</span> <span class="br0">&#40;</span><span class="kw3">user</span>, host, hfolder<span class="br0">&#41;</span><span class="br0">&#93;</span><span class="br0">&#41;</span>
&nbsp;
    <span class="co1"># setup URL in </span>
    <span class="kw1">if</span> copy_to_clipboard:
        clipboard = gtk.<span class="me1">clipboard_get</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
        clipboard.<span class="me1">set_text</span><span class="br0">&#40;</span>httplink + f<span class="br0">&#41;</span>
        <span class="co1"># make our data available to other applications</span>
        clipboard.<span class="me1">store</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp;
    <span class="co1"># Notification: Link for the clicking</span>
    <span class="kw1">if</span> popup_link:
        n3 = pynotify.<span class="me1">Notification</span><span class="br0">&#40;</span><span class="st0">&quot;Here is your link&quot;</span>,<span class="st0">&quot;&lt;a href='&quot;</span> + httplink + f + <span class="st0">&quot;'&gt;&quot;</span> + httplink + f + <span class="st0">&quot;&quot;</span><span class="br0">&#41;</span>
&nbsp;
        helper = gtk.<span class="me1">Button</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
        icon = helper.<span class="me1">render_icon</span><span class="br0">&#40;</span>gtk.<span class="me1">STOCK_DIALOG_INFO</span>, gtk.<span class="me1">ICON_SIZE_DIALOG</span><span class="br0">&#41;</span>
        n3.<span class="me1">set_icon_from_pixbuf</span><span class="br0">&#40;</span>icon<span class="br0">&#41;</span>
&nbsp;
        n3.<span class="me1">set_urgency</span><span class="br0">&#40;</span>pynotify.<span class="me1">URGENCY_NORMAL</span><span class="br0">&#41;</span>
        <span class="kw1">if</span> x3:
            n3.<span class="me1">set_hint</span><span class="br0">&#40;</span><span class="st0">&quot;x&quot;</span>, x3<span class="br0">&#41;</span>
        <span class="kw1">if</span> y3:
            n3.<span class="me1">set_hint</span><span class="br0">&#40;</span><span class="st0">&quot;y&quot;</span>, y3<span class="br0">&#41;</span>
        n3.<span class="me1">set_timeout</span><span class="br0">&#40;</span>t3<span class="br0">&#41;</span>
        n3.<span class="me1">connect</span><span class="br0">&#40;</span><span class="st0">&quot;closed&quot;</span>,closen3_cb<span class="br0">&#41;</span>
&nbsp;
        <span class="kw1">if</span> <span class="kw1">not</span> n3.<span class="me1">show</span><span class="br0">&#40;</span><span class="br0">&#41;</span>:
            <span class="kw1">print</span> <span class="st0">&quot;Failed to send notification&quot;</span>
            <span class="kw3">sys</span>.<span class="me1">exit</span><span class="br0">&#40;</span><span class="nu0">1</span><span class="br0">&#41;</span>
&nbsp;
        closen1_cb<span class="br0">&#40;</span>n1<span class="br0">&#41;</span>
        closen2_cb<span class="br0">&#40;</span>n2<span class="br0">&#41;</span>
&nbsp;
    gtk.<span class="me1">main_quit</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
    <span class="kw3">sys</span>.<span class="me1">exit</span><span class="br0">&#40;</span><span class="nu0">1</span><span class="br0">&#41;</span>
&nbsp;
<span class="co1"># Notification 1 was closed</span>
<span class="kw1">def</span> closen1_cb<span class="br0">&#40;</span>n<span class="br0">&#41;</span>:
    n1.<span class="me1">close</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
    <span class="kw1">if</span> screenshot_preview:
        n2.<span class="me1">close</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
    gtk.<span class="me1">main_quit</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp;
<span class="co1"># Notification 2 was closed</span>
<span class="kw1">def</span> closen2_cb<span class="br0">&#40;</span>n<span class="br0">&#41;</span>:
    n2.<span class="me1">close</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
    gtk.<span class="me1">main_quit</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp;
<span class="co1"># Notification 2 was closed</span>
<span class="kw1">def</span> closen3_cb<span class="br0">&#40;</span>n<span class="br0">&#41;</span>:
    n3.<span class="me1">close</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
    gtk.<span class="me1">main_quit</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp;
<span class="co1"># The Ignore button was clicked</span>
<span class="kw1">def</span> ignore_cb<span class="br0">&#40;</span>n, action<span class="br0">&#41;</span>:
    <span class="kw1">assert</span> action == <span class="st0">&quot;ignore&quot;</span>
&nbsp;
    closen1_cb<span class="br0">&#40;</span>n1<span class="br0">&#41;</span>
    closen2_cb<span class="br0">&#40;</span>n2<span class="br0">&#41;</span>
    gtk.<span class="me1">main_quit</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp;
<span class="co1"># Main</span>
<span class="kw1">def</span> main<span class="br0">&#40;</span><span class="br0">&#41;</span>:
    gtk.<span class="me1">main</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp;
<span class="co1"># Init</span>
<span class="kw1">if</span> __name__ == <span class="st0">'__main__'</span>:
    <span class="kw1">if</span> <span class="kw1">not</span> pynotify.<span class="me1">init</span><span class="br0">&#40;</span><span class="st0">&quot;Notifier 'scp' Option&quot;</span><span class="br0">&#41;</span>:
        <span class="kw3">sys</span>.<span class="me1">exit</span><span class="br0">&#40;</span><span class="nu0">1</span><span class="br0">&#41;</span>
&nbsp;
    <span class="co1"># Get latest file and build uri</span>
    start = <span class="kw3">os</span>.<span class="me1">path</span>.<span class="me1">abspath</span><span class="br0">&#40;</span>lfolder<span class="br0">&#41;</span>
    f = <span class="kw2">max</span><span class="br0">&#40;</span><span class="br0">&#91;</span><span class="br0">&#40;</span><span class="kw3">os</span>.<span class="me1">path</span>.<span class="me1">getmtime</span><span class="br0">&#40;</span><span class="kw3">os</span>.<span class="me1">path</span>.<span class="me1">join</span><span class="br0">&#40;</span>start,p<span class="br0">&#41;</span><span class="br0">&#41;</span>,p<span class="br0">&#41;</span>
         <span class="kw1">for</span> p <span class="kw1">in</span> <span class="kw3">os</span>.<span class="me1">listdir</span><span class="br0">&#40;</span>start<span class="br0">&#41;</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span>
    uri = lfolder + f
&nbsp;
    <span class="co1"># Notification: Upload to Server</span>
    n1 = pynotify.<span class="me1">Notification</span><span class="br0">&#40;</span><span class="st0">&quot;Upload to Server?&quot;</span>,<span class="st0">&quot;Copy the file '&quot;</span> + f + <span class="st0">&quot;' to the server?&quot;</span><span class="br0">&#41;</span>
&nbsp;
    helper = gtk.<span class="me1">Button</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
    icon = helper.<span class="me1">render_icon</span><span class="br0">&#40;</span>gtk.<span class="me1">STOCK_DIALOG_QUESTION</span>, gtk.<span class="me1">ICON_SIZE_DIALOG</span><span class="br0">&#41;</span>
    n1.<span class="me1">set_icon_from_pixbuf</span><span class="br0">&#40;</span>icon<span class="br0">&#41;</span>
&nbsp;
    n1.<span class="me1">set_urgency</span><span class="br0">&#40;</span>pynotify.<span class="me1">URGENCY_NORMAL</span><span class="br0">&#41;</span>
    <span class="kw1">if</span> x1:
        n1.<span class="me1">set_hint</span><span class="br0">&#40;</span><span class="st0">&quot;x&quot;</span>, x1<span class="br0">&#41;</span>
    <span class="kw1">if</span> y1:
        n1.<span class="me1">set_hint</span><span class="br0">&#40;</span><span class="st0">&quot;y&quot;</span>, y1<span class="br0">&#41;</span>
    n1.<span class="me1">set_timeout</span><span class="br0">&#40;</span>t1<span class="br0">&#41;</span>
    n1.<span class="me1">add_action</span><span class="br0">&#40;</span><span class="st0">&quot;upload&quot;</span>, <span class="st0">&quot;Yes, Upload&quot;</span>, upload_cb<span class="br0">&#41;</span>
    n1.<span class="me1">add_action</span><span class="br0">&#40;</span><span class="st0">&quot;ignore&quot;</span>, <span class="st0">&quot;Ignore&quot;</span>, ignore_cb<span class="br0">&#41;</span>
    n1.<span class="me1">connect</span><span class="br0">&#40;</span><span class="st0">&quot;closed&quot;</span>,closen1_cb<span class="br0">&#41;</span>
&nbsp;
    <span class="kw1">if</span> <span class="kw1">not</span> n1.<span class="me1">show</span><span class="br0">&#40;</span><span class="br0">&#41;</span>:
        <span class="kw1">print</span> <span class="st0">&quot;Failed to send notification&quot;</span>
        <span class="kw3">sys</span>.<span class="me1">exit</span><span class="br0">&#40;</span><span class="nu0">1</span><span class="br0">&#41;</span>
&nbsp;
    <span class="co1"># Notification: Screenshot Preview</span>
    <span class="kw1">if</span> screenshot_preview:
        n2 = pynotify.<span class="me1">Notification</span><span class="br0">&#40;</span><span class="st0">&quot;Screenshot Preview&quot;</span>, <span class="st0">&quot;&quot;</span>, uri<span class="br0">&#41;</span>
        n2.<span class="me1">set_urgency</span><span class="br0">&#40;</span>pynotify.<span class="me1">URGENCY_LOW</span><span class="br0">&#41;</span>
        <span class="kw1">if</span> x2:
            n2.<span class="me1">set_hint</span><span class="br0">&#40;</span><span class="st0">&quot;x&quot;</span>, x2<span class="br0">&#41;</span>
        <span class="kw1">if</span> y2:
            n2.<span class="me1">set_hint</span><span class="br0">&#40;</span><span class="st0">&quot;y&quot;</span>, y2<span class="br0">&#41;</span>
        n2.<span class="me1">set_timeout</span><span class="br0">&#40;</span>t2<span class="br0">&#41;</span>
        n2.<span class="me1">connect</span><span class="br0">&#40;</span><span class="st0">&quot;closed&quot;</span>,closen2_cb<span class="br0">&#41;</span>
&nbsp;
        <span class="kw1">if</span> <span class="kw1">not</span> n2.<span class="me1">show</span><span class="br0">&#40;</span><span class="br0">&#41;</span>:
            <span class="kw1">print</span> <span class="st0">&quot;Failed to send notification&quot;</span>
            <span class="kw3">sys</span>.<span class="me1">exit</span><span class="br0">&#40;</span><span class="nu0">1</span><span class="br0">&#41;</span>
&nbsp;
    main<span class="br0">&#40;</span><span class="br0">&#41;</span></pre></div></div>

<p>I also rigged up a quick gallery script to parse the incoming images http://interwebninja.com/screenshots/ &#8212; I used <a href="http://scriptandstyle.com/automatically-generate-a-photo-gallery-from-a-directory-of-images">AutoGeneratingGallery</a> for this.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.doknowevil.net/2010/06/26/scp-notifications-for-gnome-and-ubuntu-expanding-on-my-original-python-script/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="http://interwebninja.com/videos/compiz-screenshot-piped-to-notification-daemon-for-upload.ogv" length="2797703" type="video/ogg" />
		</item>
		<item>
		<title>Ubuntu Notifications (osd-notify) Sucks, notifications-daemon Rocks &#8211; Exploiting the Goodness with Compiz</title>
		<link>http://www.doknowevil.net/2010/06/25/ubuntu-notifications-osd-notify-sucks-notifications-daemon-rocks-exploiting-the-goodness-with-compiz/</link>
		<comments>http://www.doknowevil.net/2010/06/25/ubuntu-notifications-osd-notify-sucks-notifications-daemon-rocks-exploiting-the-goodness-with-compiz/#comments</comments>
		<pubDate>Sat, 26 Jun 2010 04:47:40 +0000</pubDate>
		<dc:creator>Tyler Mulligan</dc:creator>
				<category><![CDATA[Compiz]]></category>
		<category><![CDATA[Computers]]></category>
		<category><![CDATA[GNOME]]></category>
		<category><![CDATA[KDE]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Operating Systems]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[Ubuntu]]></category>
		<category><![CDATA[open source]]></category>
		<category><![CDATA[gtk]]></category>
		<category><![CDATA[markedwontfix]]></category>
		<category><![CDATA[notifications]]></category>

		<guid isPermaLink="false">http://www.doknowevil.net/?p=677</guid>
		<description><![CDATA[Introduction The long name for this blog used to be &#8220;Tyler Mulligan&#8217;s Tips and Tricks for Increasing your Efficiency&#8220;. I love finding ways to increase my efficiency and let computers do the work while I focus on more interests aspects of what the computer is providing me with. When I recognize an issue, I find]]></description>
			<content:encoded><![CDATA[<h2>Introduction</h2>
<p>The long name for this blog used to be &#8220;<a href="http://www.doknowevil.net" target="_blank">Tyler Mulligan&#8217;s Tips and Tricks for Increasing your Efficiency</a>&#8220;.  I love finding ways to increase my efficiency and let computers do the work while I focus on more interests aspects of what the computer is providing me with.  When I recognize an issue, I find a way to cut out time by streamlining the process for the most accurate repetition, like any programmer would/should/could.</p>
<p>I noticed myself taking a lot of screenshots with compiz&#8217; built in screenshot tool (I can hold a hotkey and drag a box to take newspaper style clippings).  This is very fast and simple, I highly recommend enabling this option and getting used to it.  However, I don&#8217;t care much for clicking around on clunky websites to upload images.</p>
<p>This is where my adventure starts&#8230; when I find out <a href="http://ubuntuforums.org/showthread.php?t=1517950" title="notify-osd doesn't display popup balloons">a very useful feature was deprecated and not replaced in Ubuntu</a>.  I don&#8217;t use the new notification area, it has too much I don&#8217;t need, I never liked the behavior of these new osd-notify notifications which I found out now are even more worthless (sorry team).</p>
<h2>Using Sane Notifications in Ubuntu</h2>
<p>After <a href="http://ubuntuforums.org/showpost.php?p=8559795&#038;postcount=8">reinstalling the GNOME default notifications system in Ubuntu</a> I was able to use SANE notifications that actually&#8230; KICK ASS!  I don&#8217;t understand how osd-notify is better than these which even comes with it&#8217;s own notification properties panel.  Maybe it&#8217;s an under the hood thing&#8230;</p>
<p>Regardless, there is no doubt in my mind that notifications that you hover, can still slightly see but click through but cannot perform any actions, even a close, are just plan stupid and annoying..</p>
<p><img src="http://interwebninja.com/compiz-screenshots/screenshot5.png" title="Screenshot taken with Tyler Mulligan's Notification 'scp' Option python script for ubuntu and other Linux based operating systems" /><br />
Screenshot of the script I ended up writing using the &#8220;better&#8221; notification system to ask me if I want to upload the screenshot I just took to the server.</p>
<h2>Linking the notifications</h2>
<p>I linked the notifications the following way:</p>
<p><img src="http://interwebninja.com/compiz-screenshots/screenshot3.png" title="Screenshot taken with Tyler Mulligan's Notification 'scp' Option python script for ubuntu and other Linux based operating systems" /></p>
<h2>Python Script for Notification that Prompts for File Upload to Server</h2>
<p>Knowing diddly squat about Python, I chugged forward with my classic notification popups that allow for interaction as it had the most activity around it and some examples available in /usr/share/doc/python-notify/examples/</p>
<p>I ended coming up with the following script thanks to some help from a few people in #python on irc.freenode.org</p>
<p>This is outside of the scope of this blogpost but this script assumes you have setup passwordless ssh to your server.</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"><span class="co1">#!/usr/bin/env python</span>
<span class="co1">#</span>
<span class="co1"># Title: Notification 'scp' Option</span>
<span class="co1"># Author: Tyler Mulligan (tyler@detrition.net)</span>
<span class="co1"># Date: 06/25/2010</span>
<span class="co1"># Description:</span>
<span class="co1"># Used in combination with an event, such as an action or cron</span>
<span class="co1"># the latest file from a folder will be scped to your server and will copy</span>
<span class="co1"># the http location of the that file to your clipboard</span>
<span class="co1">#</span>
<span class="co1"># Orginally developed to be piped to from compiz screenshot tool</span>
<span class="co1">#</span>
<span class="co1">#</span>
<span class="co1"># The MIT License</span>
<span class="co1">#</span>
<span class="co1"># Copyright (c) 2010 Tyler Mulligan</span>
<span class="co1">#</span>
<span class="co1"># Permission is hereby granted, free of charge, to any person obtaining a copy</span>
<span class="co1"># of this software and associated documentation files (the &quot;Software&quot;), to deal</span>
<span class="co1"># in the Software without restriction, including without limitation the rights</span>
<span class="co1"># to use, copy, modify, merge, publish, distribute, sublicense, and/or sell</span>
<span class="co1"># copies of the Software, and to permit persons to whom the Software is</span>
<span class="co1"># furnished to do so, subject to the following conditions:</span>
<span class="co1">#</span>
<span class="co1"># The above copyright notice and this permission notice shall be included in</span>
<span class="co1"># all copies or substantial portions of the Software.</span>
<span class="co1">#</span>
<span class="co1"># THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR</span>
<span class="co1"># IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,</span>
<span class="co1"># FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE</span>
<span class="co1"># AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER</span>
<span class="co1"># LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,</span>
<span class="co1"># OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN</span>
<span class="co1"># THE SOFTWARE</span>
<span class="co1">#</span>
&nbsp;
<span class="kw1">import</span> pygtk
pygtk.<span class="me1">require</span><span class="br0">&#40;</span><span class="st0">'2.0'</span><span class="br0">&#41;</span>
<span class="kw1">import</span> gtk
<span class="kw1">import</span> pynotify
<span class="kw1">import</span> <span class="kw3">sys</span>
<span class="kw1">import</span> <span class="kw3">os</span>
<span class="kw1">import</span> <span class="kw3">subprocess</span>
&nbsp;
<span class="kw3">user</span> = <span class="st0">&quot;user&quot;</span>
host = <span class="st0">&quot;server.com&quot;</span>
lfolder = <span class="st0">&quot;/home/user/screenshots/&quot;</span>
hfolder = <span class="st0">&quot;/home/remote_user/screenshots/&quot;</span>
httplink = <span class="st0">&quot;http://&quot;</span>+host+<span class="st0">&quot;/screenshots/&quot;</span>
timeout = <span class="nu0">5000</span>
&nbsp;
<span class="co1"># Set position</span>
display = gtk.<span class="me1">gdk</span>.<span class="me1">display_get_default</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
screen = display.<span class="me1">get_default_screen</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
x = screen.<span class="me1">get_width</span><span class="br0">&#40;</span><span class="br0">&#41;</span> - <span class="nu0">1</span>
y = screen.<span class="me1">get_height</span><span class="br0">&#40;</span><span class="br0">&#41;</span> - <span class="nu0">1</span>
<span class="co1">#x = 1919</span>
<span class="co1">#y = 12</span>
&nbsp;
<span class="kw1">def</span> upload_cb<span class="br0">&#40;</span>n, action<span class="br0">&#41;</span>:
    <span class="kw1">assert</span> action == <span class="st0">&quot;upload&quot;</span>
&nbsp;
    start = <span class="kw3">os</span>.<span class="me1">path</span>.<span class="me1">abspath</span><span class="br0">&#40;</span>lfolder<span class="br0">&#41;</span>
    f = <span class="kw2">max</span><span class="br0">&#40;</span><span class="br0">&#91;</span><span class="br0">&#40;</span><span class="kw3">os</span>.<span class="me1">path</span>.<span class="me1">getmtime</span><span class="br0">&#40;</span><span class="kw3">os</span>.<span class="me1">path</span>.<span class="me1">join</span><span class="br0">&#40;</span>start,x<span class="br0">&#41;</span><span class="br0">&#41;</span>,x<span class="br0">&#41;</span>
          <span class="kw1">for</span> x <span class="kw1">in</span> <span class="kw3">os</span>.<span class="me1">listdir</span><span class="br0">&#40;</span>start<span class="br0">&#41;</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span>
&nbsp;
	<span class="co1"># setup URL in clipboard</span>
    clipboard = gtk.<span class="me1">clipboard_get</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
    clipboard.<span class="me1">set_text</span><span class="br0">&#40;</span>httplink + f<span class="br0">&#41;</span>
    <span class="co1"># make our data available to other applications</span>
    clipboard.<span class="me1">store</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp;
    <span class="kw3">os</span>.<span class="me1">system</span><span class="br0">&#40;</span><span class="st0">'scp &quot;%s&quot; &quot;%s@%s:%s&quot;'</span> <span class="sy0">%</span> <span class="br0">&#40;</span>lfolder + f, <span class="kw3">user</span>, host, hfolder<span class="br0">&#41;</span> <span class="br0">&#41;</span>.<span class="me1">wait</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp;
    n.<span class="me1">close</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
    gtk.<span class="me1">main_quit</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp;
<span class="kw1">def</span> ignore_cb<span class="br0">&#40;</span>n, action<span class="br0">&#41;</span>:
    <span class="kw1">assert</span> action == <span class="st0">&quot;ignore&quot;</span>
    n.<span class="me1">close</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
    gtk.<span class="me1">main_quit</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
&nbsp;
<span class="kw1">if</span> __name__ == <span class="st0">'__main__'</span>:
    <span class="kw1">if</span> <span class="kw1">not</span> pynotify.<span class="me1">init</span><span class="br0">&#40;</span><span class="st0">&quot;Notifier 'scp' Option&quot;</span><span class="br0">&#41;</span>:
        <span class="kw3">sys</span>.<span class="me1">exit</span><span class="br0">&#40;</span><span class="nu0">1</span><span class="br0">&#41;</span>
&nbsp;
	<span class="co1"># Setup Popup</span>
    n = pynotify.<span class="me1">Notification</span><span class="br0">&#40;</span><span class="st0">&quot;Upload to Server?&quot;</span><span class="br0">&#41;</span>
    n.<span class="me1">set_urgency</span><span class="br0">&#40;</span>pynotify.<span class="me1">URGENCY_NORMAL</span><span class="br0">&#41;</span>
    n.<span class="me1">set_timeout</span><span class="br0">&#40;</span>timeout<span class="br0">&#41;</span>                          
    n.<span class="me1">set_category</span><span class="br0">&#40;</span><span class="st0">&quot;device&quot;</span><span class="br0">&#41;</span>
    n.<span class="me1">add_action</span><span class="br0">&#40;</span><span class="st0">&quot;upload&quot;</span>, <span class="st0">&quot;Yes, Upload&quot;</span>, upload_cb<span class="br0">&#41;</span>
    n.<span class="me1">add_action</span><span class="br0">&#40;</span><span class="st0">&quot;ignore&quot;</span>, <span class="st0">&quot;Ignore&quot;</span>, ignore_cb<span class="br0">&#41;</span>
&nbsp;
    <span class="co1"># Set position</span>
    n.<span class="me1">set_hint</span><span class="br0">&#40;</span><span class="st0">&quot;x&quot;</span>, x<span class="br0">&#41;</span>
    n.<span class="me1">set_hint</span><span class="br0">&#40;</span><span class="st0">&quot;y&quot;</span>, y<span class="br0">&#41;</span>
&nbsp;
    <span class="kw1">if</span> <span class="kw1">not</span> n.<span class="me1">show</span><span class="br0">&#40;</span><span class="br0">&#41;</span>:
        <span class="kw1">print</span> <span class="st0">&quot;Failed to send notification&quot;</span>
        <span class="kw3">sys</span>.<span class="me1">exit</span><span class="br0">&#40;</span><span class="nu0">1</span><span class="br0">&#41;</span>
&nbsp;
    gtk.<span class="me1">main</span><span class="br0">&#40;</span><span class="br0">&#41;</span></pre></div></div>

<p>edit: I updated the script with some position information &#8212; I love that I can put the notifications ANYWHERE on my screen.  I also variablized the timeout.</p>
<p>edit 2: Here is a video of my improved script in action &#8212; I&#8217;ll post the source later</p>
<p>http://interwebninja.com/videos/compiz-screenshot-piped-to-notification-daemon-for-upload.ogv</p>
<h2>Going Beyond</h2>
<p>The Compiz example is just something that server my immediate needs.  The possibilities are however endless.  You can for example, link this script to a cron job asking you if you want to sync some other sort of file.  Or perhaps you&#8217;d like to add multiple buttons to give yourself a folder / server choice.</p>
<p>Happy hacking</p>
]]></content:encoded>
			<wfw:commentRss>http://www.doknowevil.net/2010/06/25/ubuntu-notifications-osd-notify-sucks-notifications-daemon-rocks-exploiting-the-goodness-with-compiz/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
<enclosure url="http://cankill.us/videos/compiz-screenshot-piped-to-notification-daemon-for-upload.ogv" length="687321" type="video/ogg" />
<enclosure url="http://interwebninja.com/videos/compiz-screenshot-piped-to-notification-daemon-for-upload.ogv" length="687321" type="video/ogg" />
		</item>
		<item>
		<title>Random cow(ish) animals preaching quotes on Ubuntu 9.10</title>
		<link>http://www.doknowevil.net/2010/02/03/random-cowish-animals-preaching-quotes-on-ubuntu-910/</link>
		<comments>http://www.doknowevil.net/2010/02/03/random-cowish-animals-preaching-quotes-on-ubuntu-910/#comments</comments>
		<pubDate>Thu, 04 Feb 2010 01:02:01 +0000</pubDate>
		<dc:creator>Tyler Mulligan</dc:creator>
				<category><![CDATA[Bash]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Ubuntu]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[cowsay]]></category>
		<category><![CDATA[fortune]]></category>
		<category><![CDATA[ssh]]></category>

		<guid isPermaLink="false">http://www.doknowevil.net/?p=521</guid>
		<description><![CDATA[Looking for something interesting when I login to one of my servers, I decided to whip up the following script I appended to my ~/.bashrc file. # fortune and cowsay are needed for the snippet to work, I had to install these first sudo apt-get install fortune cowsay COWDIR=/usr/share/cowsay/cows/; COWNUM=$&#40;&#40;$RANDOM%$&#40;ls $COWDIR &#124; wc -l&#41;&#41;&#41;; COWFILE=$&#40;ls]]></description>
			<content:encoded><![CDATA[<p>Looking for something interesting when I login to one of my servers, I decided to whip up the following script I appended to my ~/.bashrc file.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"><span class="co0"># fortune and cowsay are needed for the snippet to work, I had to install these first</span>
<span class="kw2">sudo</span> <span class="kw2">apt-get</span> <span class="kw2">install</span> fortune cowsay</pre></div></div>


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"><span class="re2">COWDIR</span>=<span class="sy0">/</span>usr<span class="sy0">/</span>share<span class="sy0">/</span>cowsay<span class="sy0">/</span>cows<span class="sy0">/</span>; <span class="re2">COWNUM</span>=$<span class="br0">&#40;</span><span class="br0">&#40;</span><span class="re1">$RANDOM</span><span class="sy0">%</span>$<span class="br0">&#40;</span><span class="kw2">ls</span> <span class="re1">$COWDIR</span> <span class="sy0">|</span> <span class="kw2">wc</span> -l<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>; <span class="re2">COWFILE</span>=$<span class="br0">&#40;</span><span class="kw2">ls</span> <span class="re1">$COWDIR</span> <span class="sy0">|</span> <span class="kw2">sed</span> <span class="re5">-n</span> <span class="st_h">''</span><span class="re1">$COWNUM</span><span class="st_h">'p'</span><span class="br0">&#41;</span>; fortune <span class="sy0">|</span> cowsay <span class="re5">-f</span> <span class="re1">$COWFILE</span></pre></div></div>

<p>UPDATE:</p>
<p>Suggested by MrBougo, a shorter but perhaps more process intensive method:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;">fortune <span class="sy0">|</span> cowsay <span class="re5">-f</span> $<span class="br0">&#40;</span><span class="kw2">ls</span> <span class="sy0">/</span>usr<span class="sy0">/</span>share<span class="sy0">/</span>cowsay<span class="sy0">/</span>cows<span class="sy0">/</span> <span class="sy0">|</span> shuf <span class="sy0">|</span> <span class="kw2">head</span> -n1<span class="br0">&#41;</span></pre></div></div>

<div id="attachment_523" class="wp-caption alignnone" style="width: 1342px"><a href="http://www.doknowevil.net/wp-content/uploads/2010/02/screenshot1.png" rel="shadowbox[post-521];player=img;"><img src="http://www.doknowevil.net/wp-content/uploads/2010/02/screenshot1.png" alt="random cowsay fortune" title="random cowsay fortune" width="1332" height="850" class="size-full wp-image-523" /></a><p class="wp-caption-text">random cowsay fortune</p></div>
<p>Breaking down the script, the first 3 parts create variables and the last command executes the cowsay and quote.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"><span class="co0"># defines the directory of the cow files</span>
<span class="re2">COWDIR</span>=<span class="sy0">/</span>usr<span class="sy0">/</span>share<span class="sy0">/</span>cowsay<span class="sy0">/</span>cows<span class="sy0">/</span>;
&nbsp;
<span class="co0"># Get a random number limited to the number of files in the directory, making clever use of % (mod) and adding 1 to make sure it doesn't return 0</span>
<span class="re2">COWNUM</span>=$<span class="br0">&#40;</span><span class="br0">&#40;</span><span class="re1">$RANDOM</span><span class="sy0">%</span>$<span class="br0">&#40;</span><span class="kw2">ls</span> <span class="re1">$COWDIR</span> <span class="sy0">|</span> <span class="kw2">wc</span> -l<span class="br0">&#41;</span><span class="br0">&#41;</span>+<span class="nu0">1</span><span class="br0">&#41;</span>;
&nbsp;
<span class="co0"># list the contents of the cow dir again, pipe to sed and use the number as a random line to get the name of a file</span>
<span class="re2">COWFILE</span>=$<span class="br0">&#40;</span><span class="kw2">ls</span> <span class="re1">$COWDIR</span> <span class="sy0">|</span> <span class="kw2">sed</span> <span class="re5">-n</span> <span class="st_h">''</span><span class="re1">$COWNUM</span><span class="st_h">'p'</span><span class="br0">&#41;</span>;
&nbsp;
<span class="co0"># use fortune to get a quote, pipe to cowsay and use the file as defined above</span>
fortune <span class="sy0">|</span> cowsay <span class="re5">-f</span> <span class="re1">$COWFILE</span>;</pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://www.doknowevil.net/2010/02/03/random-cowish-animals-preaching-quotes-on-ubuntu-910/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Using Nautilus Scripting Abilities to Integrate Right Click File Enqueues with mocp</title>
		<link>http://www.doknowevil.net/2009/11/08/using-nautilus-scripting-abilities-to-integrate-right-click-file-enqueues-with-mocp/</link>
		<comments>http://www.doknowevil.net/2009/11/08/using-nautilus-scripting-abilities-to-integrate-right-click-file-enqueues-with-mocp/#comments</comments>
		<pubDate>Sun, 08 Nov 2009 15:09:20 +0000</pubDate>
		<dc:creator>Tyler Mulligan</dc:creator>
				<category><![CDATA[Bash]]></category>
		<category><![CDATA[Computers]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[Ubuntu]]></category>
		<category><![CDATA[open source]]></category>

		<guid isPermaLink="false">http://www.doknowevil.net/?p=508</guid>
		<description><![CDATA[Using moc player can prove to be both beneficial and challenging. I&#8217;ve found myself going back to exaile for a few hours on random days for the simplicity in file management via a GUI. Since I prefer to use a single media player and mocp is light weight and helpful in so many other ways]]></description>
			<content:encoded><![CDATA[<p>Using <a href="http://www.doknowevil.net/2009/07/15/the-easy-way-to-listen-to-internt-radio-in-ubuntu/">moc player</a> can prove to be both beneficial and challenging.  I&#8217;ve found myself going back to exaile for a few hours on random days for the simplicity in file management via a GUI.  Since I prefer to use a single media player and mocp is light weight and helpful in so many other ways to me&#8230; I knew I needed a solution.  It dawned on me just today how simple that solution could be with nautilus scripts.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"><span class="co0">#!/bin/bash</span>
<span class="co0"># Enqueue with mocp</span>
<span class="co0"># by Tyler &quot;-z-&quot; Mulligan</span>
<span class="co0">#</span>
<span class="co0"># This is a nautilus script.  When placed in ~/.gnome2/nautilus-scripts</span>
<span class="co0"># and chmod +x you will have the ability to right click &gt;&gt; enqueue files</span>
<span class="co0"># or directories in mocp.</span>
<span class="co0">#</span>
&nbsp;
mocp <span class="re5">-a</span> <span class="st0">&quot;$@&quot;</span></pre></div></div>

<p>Some other tips&#8230; [ and ] silently skip back and forward respectively at a rate of 5sec per second held&#8230; this beats the left and arrows which work interactively at 1sec per sec.</p>
<p>? and h bring up the help, don&#8217;t forget this.  Use this, learn the commands that work for you and happy listening.</p>
<p>Thanks to MrBougo again for helping me simplify the script further&#8230; I was originally using a for loop which is unnecessary as the quotes will help the variable expansion and mocp -a can accept multiple files/folders.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.doknowevil.net/2009/11/08/using-nautilus-scripting-abilities-to-integrate-right-click-file-enqueues-with-mocp/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Reducing pageweight by compressing production css and js files</title>
		<link>http://www.doknowevil.net/2009/09/04/reducing-pageweight-by-compressing-production-css-and-js-files/</link>
		<comments>http://www.doknowevil.net/2009/09/04/reducing-pageweight-by-compressing-production-css-and-js-files/#comments</comments>
		<pubDate>Fri, 04 Sep 2009 22:20:30 +0000</pubDate>
		<dc:creator>Tyler Mulligan</dc:creator>
				<category><![CDATA[Computers]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Organization]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[Web Applications]]></category>

		<guid isPermaLink="false">http://www.doknowevil.net/?p=497</guid>
		<description><![CDATA[I&#8217;ve been a little obsessed with improving the speed of web pages via minified javascript and css files. YUI&#8217;s team not only agrees with this, they recommend gzipping your minified js and css files. For a while I&#8217;ve been calling YUI Compressor inside my push to production scripts to do the deed. However, with this]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been a little obsessed with improving the speed of web pages via <a href="http://www.crockford.com/javascript/jsmin.html" title="Compress your css and js files" target="_blank">minified javascript and css files</a>.  YUI&#8217;s team not only agrees with this, <a href="http://yuiblog.com/blog/2006/10/16/pageweight-yui0114/" title="Compress your css and js files" target="_blank">they recommend gzipping your minified js and css files</a>.  For a while I&#8217;ve been calling <a href="http://yuilibrary.com/downloads/#yuicompressor" title="YUI Compressor -- minify your js and css files" target="_blank">YUI Compressor</a> inside my push to production scripts to do the deed.  However, with this new mention of gzipping, I think might be exploring other options such as the method mentioned on the page which originally linked me to that awesome YUI writeup; <a href="http://agachi.name/weblog/archives/2006/11/25/pack-your-javascript.htm">minifying and gzipping javascript and css on the fly using php</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.doknowevil.net/2009/09/04/reducing-pageweight-by-compressing-production-css-and-js-files/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Finding the difference in time between the first and last file in a folder using bash</title>
		<link>http://www.doknowevil.net/2009/08/22/finding-the-difference-in-time-between-the-first-and-last-file-in-a-folder-using-bash/</link>
		<comments>http://www.doknowevil.net/2009/08/22/finding-the-difference-in-time-between-the-first-and-last-file-in-a-folder-using-bash/#comments</comments>
		<pubDate>Sat, 22 Aug 2009 15:40:58 +0000</pubDate>
		<dc:creator>Tyler Mulligan</dc:creator>
				<category><![CDATA[Bash]]></category>
		<category><![CDATA[Computers]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Ubuntu]]></category>
		<category><![CDATA[snippet]]></category>

		<guid isPermaLink="false">http://www.doknowevil.net/?p=440</guid>
		<description><![CDATA[I was working on running some statistics on log files and it required me to figure out the difference to increase the accuracy. I came up with the following bash script: #!/bin/bash # get the dates start_date=$&#40;date --utc --date &#34;$(ls -Rt --full-time &#124; tail -n1 &#124; awk '{ print $6 }')&#34; +%s&#41; end_date=$&#40;date --utc --date]]></description>
			<content:encoded><![CDATA[<p>I was working on running some statistics on log files and it required me to figure out the difference to increase the accuracy.  I came up with the following bash script:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"><span class="co0">#!/bin/bash</span>
<span class="co0"># get the dates</span>
<span class="re2">start_date</span>=$<span class="br0">&#40;</span><span class="kw2">date</span> <span class="re5">--utc</span> <span class="re5">--date</span> <span class="st0">&quot;<span class="es4">$(ls -Rt --full-time | tail -n1 | awk '{ print $6 }')</span>&quot;</span> +<span class="sy0">%</span>s<span class="br0">&#41;</span>
<span class="re2">end_date</span>=$<span class="br0">&#40;</span><span class="kw2">date</span> <span class="re5">--utc</span> <span class="re5">--date</span> <span class="st0">&quot;<span class="es4">$(ls -Rt --full-time | head -n2 | tail -n1 | awk '{ print $6 }')</span>&quot;</span> +<span class="sy0">%</span>s<span class="br0">&#41;</span>
&nbsp;
<span class="co0"># find the difference</span>
<span class="re2">difference</span>=$<span class="br0">&#40;</span><span class="br0">&#40;</span>end_date-start_date<span class="br0">&#41;</span><span class="br0">&#41;</span>
&nbsp;
<span class="co0"># echo results</span>
<span class="kw3">echo</span> <span class="re1">$end_date</span> - <span class="re1">$start_date</span> = <span class="re1">$difference</span> seconds
<span class="kw3">echo</span> $<span class="br0">&#40;</span><span class="br0">&#40;</span>difference<span class="sy0">/</span><span class="nu0">86400</span><span class="br0">&#41;</span><span class="br0">&#41;</span> days</pre></div></div>

<p>Which I originally wrote as a one liner:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"><span class="re2">start_date</span>=$<span class="br0">&#40;</span><span class="kw2">date</span> <span class="re5">--utc</span> <span class="re5">--date</span> <span class="st0">&quot;<span class="es4">$(ls -Rt --full-time | tail -n1 | awk '{ print $6 }')</span>&quot;</span> +<span class="sy0">%</span>s<span class="br0">&#41;</span>; <span class="re2">end_date</span>=$<span class="br0">&#40;</span><span class="kw2">date</span> <span class="re5">--utc</span> <span class="re5">--date</span> <span class="st0">&quot;<span class="es4">$(ls -Rt --full-time | head -n2 | tail -n1 | awk '{ print $6 }')</span>&quot;</span> +<span class="sy0">%</span>s<span class="br0">&#41;</span>; <span class="re2">difference</span>=$<span class="br0">&#40;</span><span class="br0">&#40;</span>end_date-start_date<span class="br0">&#41;</span><span class="br0">&#41;</span>; <span class="kw3">echo</span> <span class="re1">$end_date</span> - <span class="re1">$start_date</span> = <span class="re1">$difference</span> seconds; <span class="kw3">echo</span> $<span class="br0">&#40;</span><span class="br0">&#40;</span>difference<span class="sy0">/</span><span class="nu0">86400</span><span class="br0">&#41;</span><span class="br0">&#41;</span> days;</pre></div></div>

<p>I got a little carried away and created this beast, which still isn&#8217;t as accurate as I need it to be but it did give me some information:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;"><span class="re2">map_1</span>=nordiccastle;<span class="re2">map_2</span>=dance;<span class="re2">start_date</span>=$<span class="br0">&#40;</span><span class="kw2">date</span> <span class="re5">--utc</span> <span class="re5">--date</span> <span class="st0">&quot;<span class="es4">$(ls -Rt --full-time | tail -n1 | awk '{ print $6 }')</span>&quot;</span> +<span class="sy0">%</span>s<span class="br0">&#41;</span>; <span class="re2">end_date</span>=$<span class="br0">&#40;</span><span class="kw2">date</span> <span class="re5">--utc</span> <span class="re5">--date</span> <span class="st0">&quot;<span class="es4">$(ls -Rt --full-time | head -n2 | tail -n1 | awk '{ print $6 }')</span>&quot;</span> +<span class="sy0">%</span>s<span class="br0">&#41;</span>; <span class="re2">difference</span>=$<span class="br0">&#40;</span><span class="br0">&#40;</span>end_date-start_date<span class="br0">&#41;</span><span class="br0">&#41;</span>; <span class="kw3">echo</span> $... Read Moreend_date - <span class="re1">$start_date</span> = <span class="re1">$difference</span> seconds; <span class="kw3">echo</span> logs <span class="kw1">for</span> $<span class="br0">&#40;</span><span class="br0">&#40;</span>difference<span class="sy0">/</span><span class="nu0">86400</span><span class="br0">&#41;</span><span class="br0">&#41;</span> days; <span class="re2">map_1_ended</span>=$<span class="br0">&#40;</span><span class="kw2">find</span> <span class="re5">-name</span> <span class="sy0">*</span>00<span class="sy0">*</span>.log <span class="sy0">|</span> <span class="kw2">xargs</span> <span class="kw2">egrep</span> <span class="re5">-A</span> <span class="nu0">4</span> <span class="st0">&quot;endmatch|timelimit -1&quot;</span> <span class="sy0">|</span><span class="kw2">grep</span> <span class="re1">$map_1</span> <span class="sy0">|</span><span class="kw2">wc</span> -l<span class="br0">&#41;</span>; <span class="re2">map_1_played</span>=$<span class="br0">&#40;</span><span class="kw2">find</span> <span class="re5">-name</span> <span class="sy0">*</span>00<span class="sy0">*</span>.log <span class="sy0">|</span> <span class="kw2">xargs</span> <span class="kw2">egrep</span> <span class="st0">&quot;gamestart&quot;</span> <span class="sy0">|</span><span class="kw2">grep</span> <span class="re1">$map_1</span> <span class="sy0">|</span><span class="kw2">wc</span> -l<span class="br0">&#41;</span>; <span class="kw3">echo</span> <span class="re1">$map_1</span> endmatched <span class="re1">$map_1_ended</span> out of <span class="re1">$map_1_played</span> <span class="kw3">times</span> played; <span class="re2">map_2_ended</span>=$<span class="br0">&#40;</span><span class="kw2">find</span> <span class="re5">-name</span> <span class="sy0">*</span>00<span class="sy0">*</span>.log <span class="sy0">|</span> <span class="kw2">xargs</span> <span class="kw2">egrep</span> <span class="re5">-A</span> <span class="nu0">4</span> <span class="st0">&quot;endmatch|timelimit -1&quot;</span> <span class="sy0">|</span><span class="kw2">grep</span> <span class="re1">$map_2</span> <span class="sy0">|</span><span class="kw2">wc</span> -l<span class="br0">&#41;</span>; <span class="re2">map_2_played</span>=$<span class="br0">&#40;</span><span class="kw2">find</span> <span class="re5">-name</span> <span class="sy0">*</span>00<span class="sy0">*</span>.log <span class="sy0">|</span> <span class="kw2">xargs</span> <span class="kw2">egrep</span> <span class="st0">&quot;gamestart&quot;</span> <span class="sy0">|</span><span class="kw2">grep</span> <span class="re1">$map_2</span> <span class="sy0">|</span><span class="kw2">wc</span> -l<span class="br0">&#41;</span>; <span class="kw3">echo</span> <span class="re1">$map_2</span> endmatched <span class="re1">$map_2_ended</span> out of <span class="re1">$map_2_played</span> <span class="kw3">times</span> played</pre></div></div>

<p>It was used to see how many times a map was played and how many times it was voted to end the match.</p>
<p>It should really be a separate script to allow for more organization</p>
]]></content:encoded>
			<wfw:commentRss>http://www.doknowevil.net/2009/08/22/finding-the-difference-in-time-between-the-first-and-last-file-in-a-folder-using-bash/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Generating sequences of numbers or characters with bash</title>
		<link>http://www.doknowevil.net/2009/08/15/generating-sequences-of-numbers-or-characters-with-bash/</link>
		<comments>http://www.doknowevil.net/2009/08/15/generating-sequences-of-numbers-or-characters-with-bash/#comments</comments>
		<pubDate>Sat, 15 Aug 2009 15:14:07 +0000</pubDate>
		<dc:creator>Tyler Mulligan</dc:creator>
				<category><![CDATA[Bash]]></category>
		<category><![CDATA[Computers]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[Ubuntu]]></category>
		<category><![CDATA[seq]]></category>

		<guid isPermaLink="false">http://www.doknowevil.net/?p=442</guid>
		<description><![CDATA[If you ever needed to generate a sequence of characters or numbers, the terminal (using bash) is a quick and easy way to do it. Lets explore some examples bash&#8217;s brace expansion: $ echo &#123;a..z&#125; a b c d e f g h i j k l m n o p q r s t]]></description>
			<content:encoded><![CDATA[<p>If you ever needed to generate a sequence of characters or numbers, the terminal (using bash) is a quick and easy way to do it.  Lets explore some examples bash&#8217;s brace expansion:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;">$ <span class="kw3">echo</span> <span class="br0">&#123;</span>a..z<span class="br0">&#125;</span>
a b c d e f g h i j k l m n o p q r s t u v <span class="kw2">w</span> x y z</pre></div></div>

<p>by defining a start and end character with the &#8216;..&#8217; in between, we tell bash to fill in the rest and echo a list for us.  Those are all lowercase, what if you wanted uppercase? simple:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;">$ <span class="kw3">echo</span> <span class="br0">&#123;</span>A..Z<span class="br0">&#125;</span>
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z</pre></div></div>

<p>Or both, with a few extra characters in the mix:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;">$ <span class="kw3">echo</span> <span class="br0">&#123;</span>A..z<span class="br0">&#125;</span>
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z <span class="br0">&#91;</span>  <span class="br0">&#93;</span> ^ _ <span class="sy0">`</span> a b c d e f g h i j k l m n o p q r s t u v <span class="kw2">w</span> x y z</pre></div></div>

<p>It doesn&#8217;t always have to be a-z though,</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;">$ <span class="kw3">echo</span> <span class="br0">&#123;</span>A..G<span class="br0">&#125;</span>
A B C D E F G</pre></div></div>

<p>This also works with numbers:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;">$ <span class="kw3">echo</span> <span class="br0">&#123;</span>0..9<span class="br0">&#125;</span>
<span class="nu0">0</span> <span class="nu0">1</span> <span class="nu0">2</span> <span class="nu0">3</span> <span class="nu0">4</span> <span class="nu0">5</span> <span class="nu0">6</span> <span class="nu0">7</span> <span class="nu0">8</span> <span class="nu0">9</span>
<span class="kw3">echo</span> <span class="br0">&#123;</span>0..100<span class="br0">&#125;</span>
<span class="nu0">0</span> <span class="nu0">1</span> <span class="nu0">2</span> <span class="nu0">3</span> <span class="nu0">4</span> <span class="nu0">5</span> <span class="nu0">6</span> <span class="nu0">7</span> <span class="nu0">8</span> <span class="nu0">9</span> <span class="nu0">10</span> <span class="nu0">11</span> <span class="nu0">12</span> <span class="nu0">13</span> <span class="nu0">14</span> <span class="nu0">15</span> <span class="nu0">16</span> <span class="nu0">17</span> <span class="nu0">18</span> <span class="nu0">19</span> <span class="nu0">20</span> <span class="nu0">21</span> <span class="nu0">22</span> <span class="nu0">23</span> <span class="nu0">24</span> <span class="nu0">25</span> <span class="nu0">26</span> <span class="nu0">27</span> <span class="nu0">28</span> <span class="nu0">29</span> <span class="nu0">30</span> <span class="nu0">31</span> <span class="nu0">32</span> <span class="nu0">33</span> <span class="nu0">34</span> <span class="nu0">35</span> <span class="nu0">36</span> <span class="nu0">37</span> <span class="nu0">38</span> <span class="nu0">39</span> <span class="nu0">40</span> <span class="nu0">41</span> <span class="nu0">42</span> <span class="nu0">43</span> <span class="nu0">44</span> <span class="nu0">45</span> <span class="nu0">46</span> <span class="nu0">47</span> <span class="nu0">48</span> <span class="nu0">49</span> <span class="nu0">50</span> <span class="nu0">51</span> <span class="nu0">52</span> <span class="nu0">53</span> <span class="nu0">54</span> <span class="nu0">55</span> <span class="nu0">56</span> <span class="nu0">57</span> <span class="nu0">58</span> <span class="nu0">59</span> <span class="nu0">60</span> <span class="nu0">61</span> <span class="nu0">62</span> <span class="nu0">63</span> <span class="nu0">64</span> <span class="nu0">65</span> <span class="nu0">66</span> <span class="nu0">67</span> <span class="nu0">68</span> <span class="nu0">69</span> <span class="nu0">70</span> <span class="nu0">71</span> <span class="nu0">72</span> <span class="nu0">73</span> <span class="nu0">74</span> <span class="nu0">75</span> <span class="nu0">76</span> <span class="nu0">77</span> <span class="nu0">78</span> <span class="nu0">79</span> <span class="nu0">80</span> <span class="nu0">81</span> <span class="nu0">82</span> <span class="nu0">83</span> <span class="nu0">84</span> <span class="nu0">85</span> <span class="nu0">86</span> <span class="nu0">87</span> <span class="nu0">88</span> <span class="nu0">89</span> <span class="nu0">90</span> <span class="nu0">91</span> <span class="nu0">92</span> <span class="nu0">93</span> <span class="nu0">94</span> <span class="nu0">95</span> <span class="nu0">96</span> <span class="nu0">97</span> <span class="nu0">98</span> <span class="nu0">99</span> <span class="nu0">100</span></pre></div></div>

<p>Descending as well as ascending</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;">$ <span class="kw3">echo</span> <span class="br0">&#123;</span>9..0<span class="br0">&#125;</span>
<span class="nu0">9</span> <span class="nu0">8</span> <span class="nu0">7</span> <span class="nu0">6</span> <span class="nu0">5</span> <span class="nu0">4</span> <span class="nu0">3</span> <span class="nu0">2</span> <span class="nu0">1</span> <span class="nu0">0</span></pre></div></div>

<p>There is another method to generate a sequence of numbers from the command line, rightfully called &#8216;seq&#8217;</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;">$ <span class="kw2">seq</span> <span class="nu0">1</span> <span class="nu0">5</span>
<span class="nu0">1</span>
<span class="nu0">2</span>
<span class="nu0">3</span>
<span class="nu0">4</span>
<span class="nu0">5</span></pre></div></div>

<p>The difference here is that it&#8217;s delimited by a new line, however, we can override that with the -s (seperator) flag</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;color: #ccc; font: 12px Consolas, Lucida Console, Monaco, monospace;">$ <span class="kw2">seq</span> <span class="re5">-s</span> <span class="st0">&quot; &quot;</span> <span class="nu0">1</span> <span class="nu0">10</span>
<span class="nu0">1</span> <span class="nu0">2</span> <span class="nu0">3</span> <span class="nu0">4</span> <span class="nu0">5</span> <span class="nu0">6</span> <span class="nu0">7</span> <span class="nu0">8</span> <span class="nu0">9</span> <span class="nu0">10</span></pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://www.doknowevil.net/2009/08/15/generating-sequences-of-numbers-or-characters-with-bash/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
