<?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>2718.us blog &#187; shell</title>
	<atom:link href="http://2718.us/blog/tag/shell/feed/" rel="self" type="application/rss+xml" />
	<link>http://2718.us/blog</link>
	<description>Miscellaneous Technological Geekery</description>
	<lastBuildDate>Tue, 18 May 2010 02:42:55 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.4</generator>
		<item>
		<title>Simplifying the Assembly of Localizations in Xcode</title>
		<link>http://2718.us/blog/2010/04/22/simplifying-the-assembly-of-localizations-in-xcode/</link>
		<comments>http://2718.us/blog/2010/04/22/simplifying-the-assembly-of-localizations-in-xcode/#comments</comments>
		<pubDate>Thu, 22 Apr 2010 20:11:51 +0000</pubDate>
		<dc:creator>2718.us</dc:creator>
				<category><![CDATA[Mac OS X]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[build script]]></category>
		<category><![CDATA[internationalization]]></category>
		<category><![CDATA[localization]]></category>
		<category><![CDATA[mac]]></category>
		<category><![CDATA[nib]]></category>
		<category><![CDATA[os x]]></category>
		<category><![CDATA[run script]]></category>
		<category><![CDATA[script]]></category>
		<category><![CDATA[sh]]></category>
		<category><![CDATA[shell]]></category>
		<category><![CDATA[shell script]]></category>
		<category><![CDATA[target]]></category>
		<category><![CDATA[xcode]]></category>
		<category><![CDATA[xib]]></category>

		<guid isPermaLink="false">http://2718.us/blog/?p=254</guid>
		<description><![CDATA[A comment on a bitbucket fork of Murky led me to &#8220;Automatically localize your nibs when building&#8220;, which suggests a great way to automate the hard developer-side stuff in localizing in Xcode&#8211;pulling the original strings from the XIB files and putting the translated strings back in.  You absolutely should read the original blog post there, [...]]]></description>
			<content:encoded><![CDATA[<p>A comment on <a href="https://bitbucket.org/philippec/murky">a bitbucket fork</a> of <a href="http://bitbucket.org/snej/murky/wiki/Home">Murky</a> led me to &#8220;<a href="http://developer.casgrain.com/?p=94">Automatically localize your nibs when building</a>&#8220;, which suggests a great way to automate the hard developer-side stuff in localizing in Xcode&#8211;pulling the original strings from the XIB files and putting the translated strings back in.  You absolutely should read the original blog post there, because I cannot adequately explain the big-picture part of the idea with a short quote.</p>
<p>My one complaint with the setup described is that the script for the &#8220;Run Script&#8221; build phase described there is a maintenance headache that I could do without.  Here&#8217;s my solution:  Create two new build targets, both of the &#8220;Shell Script&#8221; type&#8211;these are targets that just run a shell script, so they are created with only a &#8220;Run Script&#8221; build phase.  I called my two new targets &#8220;Create/Update English .strings files&#8221; and &#8220;Create/Update l10n XIBs&#8221; but you can call them whatever you want.</p>
<p>In the &#8220;Create/Update English .strings files&#8221; target&#8217;s &#8220;Run Script&#8221; phase, the script is:</p>
<div class="geshi no bash">
<div class="head"># Create/Update English .strings files</div>
<ol>
<li class="li1">
<div class="de1"><span class="kw1">for</span> xibFile <span class="kw1">in</span> <span class="st0">&quot;$PROJECT_DIR/English.lproj/&quot;</span><span class="sy0">*</span>.xib; <span class="kw1">do</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;ibtool &#8211;generate-strings-<span class="kw2">file</span> <span class="st0">&quot;${xibFile}.strings&quot;</span> <span class="st0">&quot;$xibFile&quot;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">done</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw3">exit</span> <span class="nu0">0</span></div>
</li>
</ol>
</div>
<p>This uses <code>ibtool</code> to create a strings file for every XIB in the English localization (from <code>foo.xib</code>, <code>foo.xib.strings</code> will be created).</p>
<p>In the &#8220;Create/Update l10n XIBs&#8221; target&#8217;s &#8220;Run Script&#8221; phase, the script is:</p>
<div class="geshi no bash">
<div class="head"># Create/Update l10n XIBs</div>
<ol>
<li class="li1">
<div class="de1"><span class="re2">originalResourceDirectory=</span><span class="st0">&quot;$PROJECT_DIR/English.lproj&quot;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">for</span> localizedDirectory <span class="kw1">in</span> <span class="st0">&quot;$PROJECT_DIR/&quot;</span><span class="sy0">*</span>.lproj; <span class="kw1">do</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;<span class="kw1">if</span> <span class="br0">&#91;</span> localizedDirectory <span class="sy0">!</span>= originalResourceDirectory <span class="br0">&#93;</span>; <span class="kw1">then</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="kw1">for</span> xibFile <span class="kw1">in</span> <span class="st0">&quot;${originalResourceDirectory}/&quot;</span><span class="sy0">*</span>.xib; <span class="kw1">do</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp;<span class="re2">xibBaseName=</span>$<span class="br0">&#40;</span><span class="kw2">basename</span> <span class="st0">&quot;${xibFile}&quot;</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp;ibtool &#8211;strings-<span class="kw2">file</span> <span class="st0">&quot;${localizedDirectory}/${xibBaseName}.strings&quot;</span> \</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &#8211;<span class="kw2">write</span> <span class="st0">&quot;${localizedDirectory}/${xibBaseName}&quot;</span> \</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="st0">&quot;$xibFile&quot;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="kw1">done</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;<span class="kw1">fi</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">done</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw3">exit</span> <span class="nu0">0</span></div>
</li>
</ol>
</div>
<p>This goes through every <code>.lproj</code> directory except <code>English.lproj</code> and uses <code>ibtool</code> to apply the <code>.xib.strings</code> files in those localizations to the XIB files in <code>English.lproj</code>.</p>
<p>By having these as two separate targets, they aren&#8217;t run every time I build and each part can be run on its own, on demand.  By using the power of shell scripting, I avoid having to alter the scripts for every new localization or XIB.</p>
]]></content:encoded>
			<wfw:commentRss>http://2718.us/blog/2010/04/22/simplifying-the-assembly-of-localizations-in-xcode/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>More Hackery with Slug Asterisk</title>
		<link>http://2718.us/blog/2008/08/18/more-hackery-with-slug-asterisk/</link>
		<comments>http://2718.us/blog/2008/08/18/more-hackery-with-slug-asterisk/#comments</comments>
		<pubDate>Mon, 18 Aug 2008 05:29:32 +0000</pubDate>
		<dc:creator>2718.us</dc:creator>
				<category><![CDATA[Telephony]]></category>
		<category><![CDATA[asterisk]]></category>
		<category><![CDATA[busybox]]></category>
		<category><![CDATA[coreutils]]></category>
		<category><![CDATA[date]]></category>
		<category><![CDATA[dialplan]]></category>
		<category><![CDATA[ipkg]]></category>
		<category><![CDATA[nohup]]></category>
		<category><![CDATA[nslu2]]></category>
		<category><![CDATA[shell]]></category>
		<category><![CDATA[shell script]]></category>
		<category><![CDATA[sleep]]></category>
		<category><![CDATA[slug]]></category>
		<category><![CDATA[system]]></category>
		<category><![CDATA[touch]]></category>
		<category><![CDATA[unslung]]></category>
		<category><![CDATA[wake-up]]></category>
		<category><![CDATA[wake-up call]]></category>
		<category><![CDATA[wakeup]]></category>
		<category><![CDATA[wakeup call]]></category>

		<guid isPermaLink="false">http://2718.us/blog/?p=95</guid>
		<description><![CDATA[I wanted to make my slug running Asterisk do wakeup calls, since I currently pay $11/month for a daily wakeup call service and they&#8217;ll only try up to 4 times.  As my starting point, I was using this dialplan from the-asterisk-book.com: &#91;hotel-intern&#93; exten =&#62; _*77*XXXXXXXXXXXX,1,Answer&#40;&#41; exten =&#62; _*77*XXXXXXXXXXXX,n,Set&#40;year=$&#123;EXTEN:4:4&#125;&#41; exten =&#62; _*77*XXXXXXXXXXXX,n,Set&#40;month=$&#123;EXTEN:8:2&#125;&#41; exten =&#62; _*77*XXXXXXXXXXXX,n,Set&#40;day=$&#123;EXTEN:10:2&#125;&#41; exten [...]]]></description>
			<content:encoded><![CDATA[<p>I wanted to make my slug running Asterisk do wakeup calls, since I currently pay $11/month for a daily wakeup call service and they&#8217;ll only try up to 4 times.  As my starting point, I was using this dialplan <a href="http://www.the-asterisk-book.com/unstable/call-file.html">from the-asterisk-book.com</a>:</p>
<div class="geshi no php">
<ol>
<li class="li1">
<div class="de1"><span class="br0">&#91;</span>hotel<span class="sy0">-</span>intern<span class="br0">&#93;</span></div>
</li>
<li class="li1">
<div class="de1">exten <span class="sy0">=&gt;</span> <span class="kw3">_</span><span class="sy0">*</span><span class="nu0">77</span><span class="sy0">*</span>XXXXXXXXXXXX<span class="sy0">,</span><span class="nu0">1</span><span class="sy0">,</span>Answer<span class="br0">&#40;</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">exten <span class="sy0">=&gt;</span> <span class="kw3">_</span><span class="sy0">*</span><span class="nu0">77</span><span class="sy0">*</span>XXXXXXXXXXXX<span class="sy0">,</span>n<span class="sy0">,</span>Set<span class="br0">&#40;</span>year<span class="sy0">=</span>$<span class="br0">&#123;</span>EXTEN<span class="sy0">:</span><span class="nu0">4</span><span class="sy0">:</span><span class="nu0">4</span><span class="br0">&#125;</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">exten <span class="sy0">=&gt;</span> <span class="kw3">_</span><span class="sy0">*</span><span class="nu0">77</span><span class="sy0">*</span>XXXXXXXXXXXX<span class="sy0">,</span>n<span class="sy0">,</span>Set<span class="br0">&#40;</span>month<span class="sy0">=</span>$<span class="br0">&#123;</span>EXTEN<span class="sy0">:</span><span class="nu0">8</span><span class="sy0">:</span><span class="nu0">2</span><span class="br0">&#125;</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">exten <span class="sy0">=&gt;</span> <span class="kw3">_</span><span class="sy0">*</span><span class="nu0">77</span><span class="sy0">*</span>XXXXXXXXXXXX<span class="sy0">,</span>n<span class="sy0">,</span>Set<span class="br0">&#40;</span>day<span class="sy0">=</span>$<span class="br0">&#123;</span>EXTEN<span class="sy0">:</span><span class="nu0">10</span><span class="sy0">:</span><span class="nu0">2</span><span class="br0">&#125;</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">exten <span class="sy0">=&gt;</span> <span class="kw3">_</span><span class="sy0">*</span><span class="nu0">77</span><span class="sy0">*</span>XXXXXXXXXXXX<span class="sy0">,</span>n<span class="sy0">,</span>Set<span class="br0">&#40;</span>hours<span class="sy0">=</span>$<span class="br0">&#123;</span>EXTEN<span class="sy0">:</span><span class="nu0">12</span><span class="sy0">:</span><span class="nu0">2</span><span class="br0">&#125;</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">exten <span class="sy0">=&gt;</span> <span class="kw3">_</span><span class="sy0">*</span><span class="nu0">77</span><span class="sy0">*</span>XXXXXXXXXXXX<span class="sy0">,</span>n<span class="sy0">,</span>Set<span class="br0">&#40;</span>minutes<span class="sy0">=</span>$<span class="br0">&#123;</span>EXTEN<span class="sy0">:</span><span class="nu0">14</span><span class="sy0">:</span><span class="nu0">2</span><span class="br0">&#125;</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">exten <span class="sy0">=&gt;</span> <span class="kw3">_</span><span class="sy0">*</span><span class="nu0">77</span><span class="sy0">*</span>XXXXXXXXXXXX<span class="sy0">,</span>n<span class="sy0">,</span>NoOp<span class="br0">&#40;</span>Wake<span class="sy0">-</span>up call scheduled <span class="kw1">for</span> $<span class="br0">&#123;</span>CALLERID<span class="br0">&#40;</span>num<span class="br0">&#41;</span><span class="br0">&#125;</span> at $<span class="br0">&#123;</span>hours<span class="br0">&#125;</span><span class="sy0">:</span>$<span class="br0">&#123;</span>minutes<span class="br0">&#125;</span> on $<span class="br0">&#123;</span>day<span class="br0">&#125;</span><span class="sy0">.</span>$<span class="br0">&#123;</span>month<span class="br0">&#125;</span><span class="sy0">.</span>$<span class="br0">&#123;</span>year<span class="br0">&#125;</span><span class="sy0">.</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">exten <span class="sy0">=&gt;</span> <span class="kw3">_</span><span class="sy0">*</span><span class="nu0">77</span><span class="sy0">*</span>XXXXXXXXXXXX<span class="sy0">,</span>n<span class="sy0">,</span><span class="kw3">System</span><span class="br0">&#40;</span><span class="kw3">echo</span> <span class="sy0">-</span>e <span class="st0">&quot;Channel: SIP/${CALLERID(num)}<span class="es0">\\</span>nContext: wake-up<span class="es0">\\</span>nExtension: 23&quot;</span> <span class="sy0">&gt;</span> <span class="sy0">/</span>tmp<span class="sy0">/</span>$<span class="br0">&#123;</span>UNIQUEID<span class="br0">&#125;</span><span class="sy0">.</span>call<span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">exten <span class="sy0">=&gt;</span> <span class="kw3">_</span><span class="sy0">*</span><span class="nu0">77</span><span class="sy0">*</span>XXXXXXXXXXXX<span class="sy0">,</span>n<span class="sy0">,</span><span class="kw3">System</span><span class="br0">&#40;</span><span class="kw3">touch</span> <span class="sy0">-</span>t $<span class="br0">&#123;</span>year<span class="br0">&#125;</span>$<span class="br0">&#123;</span>month<span class="br0">&#125;</span>$<span class="br0">&#123;</span>day<span class="br0">&#125;</span>$<span class="br0">&#123;</span>hours<span class="br0">&#125;</span>$<span class="br0">&#123;</span>minutes<span class="br0">&#125;</span> <span class="sy0">/</span>tmp<span class="sy0">/</span>$<span class="br0">&#123;</span>UNIQUEID<span class="br0">&#125;</span><span class="sy0">.</span>call<span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">exten <span class="sy0">=&gt;</span> <span class="kw3">_</span><span class="sy0">*</span><span class="nu0">77</span><span class="sy0">*</span>XXXXXXXXXXXX<span class="sy0">,</span>n<span class="sy0">,</span><span class="kw3">System</span><span class="br0">&#40;</span>mv <span class="sy0">/</span>tmp<span class="sy0">/</span>$<span class="br0">&#123;</span>UNIQUEID<span class="br0">&#125;</span><span class="sy0">.</span>call <span class="sy0">/</span><span class="kw2">var</span><span class="sy0">/</span>spool<span class="sy0">/</span>asterisk<span class="sy0">/</span>outgoing<span class="sy0">/</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">exten <span class="sy0">=&gt;</span> <span class="kw3">_</span><span class="sy0">*</span><span class="nu0">77</span><span class="sy0">*</span>XXXXXXXXXXXX<span class="sy0">,</span>n<span class="sy0">,</span>Playback<span class="br0">&#40;</span>rqsted<span class="sy0">-</span>wakeup<span class="sy0">-</span><span class="kw1">for</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">exten <span class="sy0">=&gt;</span> <span class="kw3">_</span><span class="sy0">*</span><span class="nu0">77</span><span class="sy0">*</span>XXXXXXXXXXXX<span class="sy0">,</span>n<span class="sy0">,</span>SayNumber<span class="br0">&#40;</span>$<span class="br0">&#123;</span>hours<span class="br0">&#125;</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">exten <span class="sy0">=&gt;</span> <span class="kw3">_</span><span class="sy0">*</span><span class="nu0">77</span><span class="sy0">*</span>XXXXXXXXXXXX<span class="sy0">,</span>n<span class="sy0">,</span>SayNumber<span class="br0">&#40;</span>$<span class="br0">&#123;</span>minutes<span class="br0">&#125;</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">exten <span class="sy0">=&gt;</span> <span class="kw3">_</span><span class="sy0">*</span><span class="nu0">77</span><span class="sy0">*</span>XXXXXXXXXXXX<span class="sy0">,</span>n<span class="sy0">,</span>Hangup<span class="br0">&#40;</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#91;</span>wake<span class="sy0">-</span>up<span class="br0">&#93;</span></div>
</li>
<li class="li1">
<div class="de1">exten <span class="sy0">=&gt;</span> <span class="nu0">23</span><span class="sy0">,</span><span class="nu0">1</span><span class="sy0">,</span>Answer<span class="br0">&#40;</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">exten <span class="sy0">=&gt;</span> <span class="nu0">23</span><span class="sy0">,</span>n<span class="sy0">,</span>Wait<span class="br0">&#40;</span><span class="nu0">1</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">exten <span class="sy0">=&gt;</span> <span class="nu0">23</span><span class="sy0">,</span>n<span class="sy0">,</span>Playback<span class="br0">&#40;</span>this<span class="sy0">-</span>is<span class="sy0">-</span>yr<span class="sy0">-</span>wakeup<span class="sy0">-</span>call<span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">exten <span class="sy0">=&gt;</span> <span class="nu0">23</span><span class="sy0">,</span>n<span class="sy0">,</span>Wait<span class="br0">&#40;</span><span class="nu0">1</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">exten <span class="sy0">=&gt;</span> <span class="nu0">23</span><span class="sy0">,</span>n<span class="sy0">,</span>Hangup<span class="br0">&#40;</span><span class="br0">&#41;</span></div>
</li>
</ol>
</div>
<p>The problem is that my slug is unslung, running busybox for most basic *nix tools and busybox&#8217;s touch command doesn&#8217;t support the -t option, so I can&#8217;t set the modification time on the file to properly queue it.  My half-assed workaround is a shell script (because I couldn&#8217;t get the System() command to run the whole string, try as I might) that nohups a background shell process that sleeps for the difference in seconds between now and the wakeup time, then creates the call file.  Not great for far-future scheduling or for large numbers of calls and it won&#8217;t survive a reboot, but it&#8217;s a start.</p>
<div class="geshi no bash">
<div class="head">#!/bin/sh</div>
<ol>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">nohup</span> <span class="kw2">sh</span> -c <span class="st0">&quot;sleep $((`/bin/date &#8211;date=&quot;</span>$<span class="nu0">1</span><span class="st0">&quot; +&quot;</span><span class="sy0">%</span>s<span class="st0">&quot;` &#8211; `/bin/date +&quot;</span><span class="sy0">%</span>s<span class="st0">&quot;`)) ; echo -e &#39;Channel: $2<span class="es0">\\</span>nContext: wake-up<span class="es0">\\</span>nExtension: 23&#39; &gt; /tmp/$3.call ; mv /tmp/$3.call /opt/var/spool/asterisk/outgoing/&quot;</span> <span class="sy0">&gt;/</span>dev<span class="sy0">/</span>null <span class="sy0">&amp;</span></div>
</li>
</ol>
</div>
<p>My Asterisk diaplan macro passes the target time/date string as the first argument, the target channel as the second, and the ${UNIQUEID} as the third.  One further wrinkle:  busybox 1.3.1, which was what came with the unslung firmware I used, doesn&#8217;t have nohup, so it won&#8217;t work; busybox 1.10.3 is what ipkg installed into /opt/ and has nohup, but the date command in 1.10.3 didn&#8217;t seem to support &#8211;date (at all, or maybe just not properly), so nohup is a reference to the 1.10.3 busybox in /opt/bin while /bin/date is a reference to the original 1.3.1 busybox.  Stupid, but it works.</p>
<p>(Oh, and as I told the last person I saw wearing a t-shirt that said &#8220;If it&#8217;s stupid, but it works, then it isn&#8217;t stupid,&#8221; there&#8217;s definitely such a thing as works-but-stupid&#8211;this script hackery is such a thing.  The better solution, space permitting, is probably just to install the coreutils package so as to have proper non-busybox touch and date)</p>
]]></content:encoded>
			<wfw:commentRss>http://2718.us/blog/2008/08/18/more-hackery-with-slug-asterisk/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

