<?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>Kevin Deldycke &#187; CLI</title> <atom:link href="http://kevin.deldycke.com/tag/command-line-interface/feed/" rel="self" type="application/rss+xml" /><link>http://kevin.deldycke.com</link> <description>Free software engineer &#38; wannabe videomaker</description> <lastBuildDate>Fri, 03 Feb 2012 19:08:27 +0000</lastBuildDate> <language>en</language> <sy:updatePeriod>hourly</sy:updatePeriod> <sy:updateFrequency>1</sy:updateFrequency> <generator>http://wordpress.org/?v=3.3.1</generator> <item><title>GPG commands</title><link>http://kevin.deldycke.com/2011/11/gpg-commands/</link> <comments>http://kevin.deldycke.com/2011/11/gpg-commands/#comments</comments> <pubDate>Tue, 08 Nov 2011 11:20:19 +0000</pubDate> <dc:creator>Kev</dc:creator> <category><![CDATA[English]]></category> <category><![CDATA[CLI]]></category> <category><![CDATA[cryptography]]></category> <category><![CDATA[GPG]]></category> <category><![CDATA[Linux]]></category> <category><![CDATA[security]]></category><guid isPermaLink="false">http://kevin.deldycke.com/?p=3560</guid> <description><![CDATA[Generate a key (interactive mode): You can use the key generator in an unattended mode. Values in the example below are the same as the defaults proposed in the interactive mode above. Parameters in comments are there for reference: List &#8230; <a href="http://kevin.deldycke.com/2011/11/gpg-commands/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description> <content:encoded><![CDATA[<ul><li>Generate a key (interactive mode):<pre class="brush: bash; title: ; notranslate">
gpg --gen-key
</pre></li><li>You can use the key generator in an unattended mode. Values in the example below are the same as the defaults proposed in the interactive mode above. Parameters in comments are there for reference:<pre class="brush: bash; title: ; notranslate">
gpg --gen-key --batch &lt;&lt;EOF
Key-Type: RSA
Key-Length: 2048
Subkey-Type: RSA
Subkey-Length: 2048
Expire-Date: 0
Name-Real: Kevin
# Name-Email: kevin@deldycke.com
# Name-Comment: My auto-generated key
# Passphrase: my_secret_passphrase
EOF
</pre></li><li>List available keys for the current user:<pre class="brush: bash; title: ; notranslate">
gpg --list-keys
</pre></li><li>Decrypt a file:<pre class="brush: bash; title: ; notranslate">
gpg --decrypt archive.001.tar.gpg --output archive.001.tar
</pre></li><li>Same as above but for a collection of files:<pre class="brush: bash; title: ; notranslate">
gpg --multifile --decrypt archive.*.tar.gpg
</pre></li></ul> ]]></content:encoded> <wfw:commentRss>http://kevin.deldycke.com/2011/11/gpg-commands/feed/</wfw:commentRss> <slash:comments>1</slash:comments> </item> <item><title>Bazaar commands</title><link>http://kevin.deldycke.com/2011/11/bazaar-commands/</link> <comments>http://kevin.deldycke.com/2011/11/bazaar-commands/#comments</comments> <pubDate>Tue, 01 Nov 2011 11:46:26 +0000</pubDate> <dc:creator>Kev</dc:creator> <category><![CDATA[English]]></category> <category><![CDATA[bazaar]]></category> <category><![CDATA[CLI]]></category> <category><![CDATA[development]]></category> <category><![CDATA[Launchpad]]></category> <category><![CDATA[Linux]]></category> <category><![CDATA[OpenERP]]></category> <category><![CDATA[programming]]></category> <category><![CDATA[Version control]]></category><guid isPermaLink="false">http://kevin.deldycke.com/?p=3638</guid> <description><![CDATA[Check-out in the local openerp-server folder the 6.0 branch of the OpenERP server project from Launchpad: Same command as above, but fetch a particular revision: Get revision number of the local copy we sit in: Remove lock file on the &#8230; <a href="http://kevin.deldycke.com/2011/11/bazaar-commands/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description> <content:encoded><![CDATA[<ul><li>Check-out in the local <code>openerp-server</code> folder the <code>6.0</code> branch of the OpenERP server project from Launchpad:<pre class="brush: bash; title: ; notranslate">
bzr branch lp:openobject-server/6.0 openerp-server
</pre></li><li>Same command as above, but fetch a particular revision:<pre class="brush: bash; title: ; notranslate">
bzr branch lp:openobject-server/6.0 -r 3425 openerp-server
</pre></li><li>Get revision number of the local copy we sit in:<pre class="brush: bash; title: ; notranslate">
bzr revno ./
</pre></li><li>Remove lock file on the current repository:<pre class="brush: bash; title: ; notranslate">
bzr break-lock
</pre></li></ul> ]]></content:encoded> <wfw:commentRss>http://kevin.deldycke.com/2011/11/bazaar-commands/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>PostgreSQL commands</title><link>http://kevin.deldycke.com/2011/10/postgresql-commands/</link> <comments>http://kevin.deldycke.com/2011/10/postgresql-commands/#comments</comments> <pubDate>Tue, 25 Oct 2011 10:40:47 +0000</pubDate> <dc:creator>Kev</dc:creator> <category><![CDATA[English]]></category> <category><![CDATA[CLI]]></category> <category><![CDATA[database]]></category> <category><![CDATA[Linux]]></category> <category><![CDATA[PostgreSQL]]></category><guid isPermaLink="false">http://kevin.deldycke.com/?p=3646</guid> <description><![CDATA[Update the default configuration to allow direct authentication from the local machine: Same as above but for local IPv4 and IPv6 connexions: List databases: Create a new kevin_db database with the kevin user: Remove the database we created above: To &#8230; <a href="http://kevin.deldycke.com/2011/10/postgresql-commands/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description> <content:encoded><![CDATA[<ul><li>Update the default configuration to allow direct authentication from the local machine:<pre class="brush: bash; title: ; notranslate">
sed -i 's/^local\s\+all\s\+all\s\+ident/local all all trust/g' /etc/postgresql/8.4/main/pg_hba.conf
</pre></li><li>Same as above but for local IPv4 and IPv6 connexions:<pre class="brush: bash; title: ; notranslate">
sed -i 's/^host\s\+all\s\+all\s\+\(.*\)\s\+md5/host all all \1 trust/g' /etc/postgresql/8.4/main/pg_hba.conf
</pre></li><li>List databases:<pre class="brush: bash; title: ; notranslate">
psql --list -U kevin
</pre></li><li>Create a new <code>kevin_db</code> database with the <code>kevin</code> user:<pre class="brush: bash; title: ; notranslate">
createdb -U kevin kevin_db
</pre></li><li>Remove the database we created above:<pre class="brush: bash; title: ; notranslate">
dropdb kevin_db -U kevin
</pre></li><li>To connect to a particular database:<pre class="brush: bash; title: ; notranslate">
psql -d database_id
</pre></li><li>Show us how a table of a specific database can be recreated:<pre class="brush: bash; title: ; notranslate">
pg_dump my_database --schema-only --table=my_table
</pre></li><li>Dump a database in a compressed format:<pre class="brush: bash; title: ; notranslate">
pg_dump my_database -v --format=c --file=/var/lib/postgresql/my_database-db-2011-12-19.dump
</pre></li><li>Restore a compressed dump:<pre class="brush: bash; title: ; notranslate">
pg_restore -U my_user -d my_database /var/lib/postgresql/my_database-db-2011-12-19.dump
</pre></li><li>Import an SQL file to a database:<pre class="brush: bash; title: ; notranslate">
psql --username kevin -d kevin_db &lt; ./database_dump.sql
</pre></li><li>Search if <code>kevin</code> is a PostgreSQL user:<pre class="brush: bash; title: ; notranslate">
sudo -u postgres psql --tuples-only --no-align --command &quot;SELECT usename FROM pg_user;&quot; | grep --quiet 'kevin' &amp;&amp; echo 'User found !' || echo 'User not found !'
</pre></li><li>Set the owner of a database:<pre class="brush: sql; title: ; notranslate">
ALTER DATABASE db_id OWNER TO user_id;
</pre></li><li>Set the owner of all tables from the <code>MY_DB_ID</code> database to <code>MY_DB_USER</code> (<a href="http://stackoverflow.com/questions/1348126/modify-owner-on-all-tables-simultaneously-in-postgresql">source</a>):<pre class="brush: bash; title: ; notranslate">
for tbl in `psql -qAt -c &quot;SELECT tablename FROM pg_tables WHERE schemaname = 'public';&quot; MY_DB_ID` ; do psql -c &quot;ALTER TABLE $tbl OWNER TO MY_DB_USER&quot; MY_DB_ID ; done
</pre></li><li>Same as above but for sequences and views:<pre class="brush: bash; title: ; notranslate">
for tbl in `psql -qAt -c &quot;SELECT sequence_name FROM information_schema.sequences WHERE sequence_schema = 'public';&quot; MY_DB_ID` ; do psql -c &quot;ALTER TABLE $tbl OWNER TO MY_DB_USER&quot; MY_DB_ID ; done
for tbl in `psql -qAt -c &quot;SELECT table_name FROM information_schema.views WHERE table_schema = 'public';&quot; MY_DB_ID` ; do psql -c &quot;ALTER TABLE $tbl OWNER TO MY_DB_USER&quot; MY_DB_ID ; done
</pre></li><li>Remove from a table all rows older than a month:<pre class="brush: bash; title: ; notranslate">
sudo -u postgres psql -d database_id  --command &quot;DELETE FROM smile_log WHERE log_date &gt; current_date - interval '1 month';&quot;
</pre></li><li>Monitor queries being run in real time:<pre class="brush: bash; title: ; notranslate">
watch -n 1 'sudo -u postgres psql --tuples-only --command &quot;SELECT datname, procpid, date_trunc(\$\$second\$\$, age(current_timestamp, xact_start)), current_query FROM pg_stat_activity;&quot;'
</pre></li><li>Disable all triggers of a table, excluding triggers that are used to implement foreign key constraints:<pre class="brush: bash; title: ; notranslate">
ALTER TABLE table_id DISABLE TRIGGER ALL;
</pre></li><li>List all constraints of your database (<a href="http://solaimurugan.blogspot.com/2010/10/list-out-all-forien-key-constraints.html">source</a>):<pre class="brush: sql; title: ; notranslate">
SELECT tc.constraint_name,
tc.constraint_type,
tc.table_name,
kcu.column_name,
tc.is_deferrable,
tc.initially_deferred,
rc.match_option AS match_type,
rc.update_rule AS on_update,
rc.delete_rule AS on_delete,
ccu.table_name AS references_table,
ccu.column_name AS references_field
FROM information_schema.table_constraints tc

LEFT JOIN information_schema.key_column_usage kcu
ON tc.constraint_catalog = kcu.constraint_catalog
AND tc.constraint_schema = kcu.constraint_schema
AND tc.constraint_name = kcu.constraint_name

LEFT JOIN information_schema.referential_constraints rc
ON tc.constraint_catalog = rc.constraint_catalog
AND tc.constraint_schema = rc.constraint_schema
AND tc.constraint_name = rc.constraint_name

LEFT JOIN information_schema.constraint_column_usage ccu
ON rc.unique_constraint_catalog = ccu.constraint_catalog
AND rc.unique_constraint_schema = ccu.constraint_schema
AND rc.unique_constraint_name = ccu.constraint_name

WHERE lower(tc.constraint_type) in ('foreign key');
</pre></li><li>And finally, here is a list of <a href="http://linuxhow-tos.blogspot.com/2011/03/monitor-postgresql-with-queries.html">great monitoring one-liners</a>.</li></ul> ]]></content:encoded> <wfw:commentRss>http://kevin.deldycke.com/2011/10/postgresql-commands/feed/</wfw:commentRss> <slash:comments>1</slash:comments> </item> <item><title>How I Open-Sourced an Internal Corporate Project (WebPing)</title><link>http://kevin.deldycke.com/2011/08/how-open-source-an-internal-corporate-project-webping/</link> <comments>http://kevin.deldycke.com/2011/08/how-open-source-an-internal-corporate-project-webping/#comments</comments> <pubDate>Tue, 30 Aug 2011 10:18:01 +0000</pubDate> <dc:creator>Kev</dc:creator> <category><![CDATA[English]]></category> <category><![CDATA[CLI]]></category> <category><![CDATA[Git]]></category> <category><![CDATA[GitHub]]></category> <category><![CDATA[Linux]]></category> <category><![CDATA[Perl]]></category> <category><![CDATA[Python]]></category> <category><![CDATA[regexp]]></category> <category><![CDATA[Subversion]]></category> <category><![CDATA[trac]]></category> <category><![CDATA[webping]]></category><guid isPermaLink="false">http://kevin.deldycke.com/?p=3749</guid> <description><![CDATA[2 weeks ago I released WebPing. This article is more or less the same I wrote 4 months ago when I released the FTT project and needed to move it from SVN to Git. But this time I added more &#8230; <a href="http://kevin.deldycke.com/2011/08/how-open-source-an-internal-corporate-project-webping/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description> <content:encoded><![CDATA[<p><a href="http://kevin.deldycke.com/2011/08/webping-open-sourced/">2 weeks ago I released WebPing</a>. This article is more or less the same I wrote 4 months ago when I <a href="http://kevin.deldycke.com/2011/03/feed-tracking-tool-released-open-source-license/">released the FTT project</a> and needed to <a href=http://kevin.deldycke.com/2011/04/ftt-migration-subversion-git/>move it from SVN to Git</a>. But this time I added more details on how I removed all sensible informations that were hard-coded in the project files.</p><h2>Subversion to Git migration</h2><p>Everything starts out of a local copy of the Subversion repository that was hosting the WebPing project since its inception:</p><pre class="brush: bash; title: ; notranslate">
$ rm -rf ./svn-repository-copy
$ tar xvzf ./svn-repository-copy.tar.gz
$ kill `ps -ef | grep svnserve | awk '{print $2}'`
$ svnserve --daemon --listen-port 3690 --root ./svn-repository-copy
</pre><p>Let&#8217;s initialize a Git repository:</p><pre class="brush: bash; title: ; notranslate">
$ rm -rf ./webping-git
$ mkdir ./webping-git
$ cd ./webping-git
$ git init
$ git commit --allow-empty -m 'Initial commit'
$ git tag &quot;init&quot;
</pre><p>We now migrate the code from Subversion to Git:</p><pre class="brush: bash; title: ; notranslate">
$ git svn init --no-metadata --username deldycke svn://localhost:3690
$ git svn fetch
$ git rebase --onto git-svn master
$ rm -rf ./.git/svn/
$ rm -rf ./.git/refs/original/
$ git reflog expire --all
$ git gc --aggressive --prune
</pre><h2>Removing unrelated files and folders</h2><p>As WebPing was not alone in the original Subversion repository, we need to clean up the latter and only keep code of the former. Worse, WebPing didn&#8217;t started its life in a dedicated subfolder, but as a tool of another project, and jumped from folders to folders. After identifying in the history all places were WebPing lived once, I came up with this big, convoluted command line to do the cleaning:</p><pre class="brush: bash; title: ; notranslate">
$ git filter-branch --force --prune-empty --tree-filter 'find ./ -not -ipath &quot;*webping*&quot; -and -not -path &quot;./other-project/trunk/tools/web-ping*&quot; -and -not -path &quot;./other-project/trunk/tools&quot; -and -not -path &quot;./other-project/trunk&quot; -and -not -path &quot;./other-project&quot; -and -not -path &quot;./.git*&quot; -and -not -path &quot;./&quot; | xargs rm -rf' -- --all
</pre><p>Strangely enough, my <code>init</code> tag went of after the command above. So I had to rebased it to get it in line:</p><pre class="brush: bash; title: ; notranslate">
$ git rebase init master
</pre><p>We can now remove SVN tags and branches, get rid of the imported <code>git-svn</code> branch, and clean up our Git repository:</p><pre class="brush: bash; title: ; notranslate">
$ git filter-branch --force --prune-empty --tree-filter 'find -path &quot;./WebPing/tags*&quot; | xargs rm -rf' -- --all
$ git filter-branch --force --prune-empty --tree-filter 'find -path &quot;./WebPing/branches*&quot; | xargs rm -rf' -- --all
$ git branch -r -D git-svn
$ rm -rf ./.git/svn/
$ rm -rf ./.git/refs/original/
$ git reflog expire --all
$ git gc --aggressive --prune
</pre><p>If I now only have WebPing code in the repository, it still jumps through the history between these following locations:</p><ul><li><code>other-project/trunk/tools/web-ping.py</code></li><li><code>other-project/trunk/tools/web-ping/</code></li><li><code>WebPing/trunk/</code></li></ul><p>Using a series of <code>git filter-branch</code> invocations, I managed to move everything to the root of the repository:</p><pre class="brush: bash; title: ; notranslate">
$ git filter-branch --force --prune-empty --tree-filter 'test -d ./other-project/trunk/tools &amp;&amp; cp -axv ./other-project/trunk/tools/* ./ &amp;&amp; rm -rf ./other-project/trunk/tools || echo &quot;No tools folder found&quot;' -- --all
$ git filter-branch --force --prune-empty --tree-filter 'test -d ./other-project/trunk/tools/web-ping &amp;&amp; cp -axv ./other-project/trunk/tools/web-ping/* ./ &amp;&amp; rm -rf ./other-project/trunk/tools/web-ping || echo &quot;No web-ping folder found&quot;' -- --all
$ git filter-branch --force --prune-empty --tree-filter 'test -d ./WebPing/trunk &amp;&amp; cp -axv ./WebPing/trunk/* ./ &amp;&amp; rm -rf ./WebPing/trunk || echo &quot;No trunk folder found&quot;' -- --all
</pre><h2>Hide and obfuscate hard-coded content</h2><p>As WebPing was created for internal needs in my previous job, its original code base contains lots of references to the former infrastructure it lives in. My professional standards requires me to remove all these sensible informations before making WebPing available to the public.</p><p>For example, here is the commands which allowed me to remove all references to hostnames of our intranets:</p><pre class="brush: bash; title: ; notranslate">
$ git filter-branch --force --prune-empty --tree-filter 'find . -type f -exec perl -i -pe &quot;s/([\w-.]*?)\.(company(-intranet|-extention)?)\.(fr|com|net|org)/intranet\.example\.com/g&quot; &quot;{}&quot; \;' -- --all
</pre><p>The Perl one-liner embedded in the command above will only apply the regular expression on a line-by-line basis. If you want to have the regexp applied on the whole content of each file, you have to use Perl&#8217;s <em>slurp</em> mode (<a href="http://www.math.uiuc.edu/~hildebr/computer/perltips.html">source of that tip</a>):</p><pre class="brush: bash; title: ; notranslate">
$ git filter-branch --force --prune-empty --tree-filter 'perl -0777 -i -pe &quot;s/MAILING_LIST\s*=\s*\[(.*?)\]/MAILING_LIST = \[\]/gs&quot; ./web-ping.py' -- --all
</pre><p>The specific example above helped me removed the content of the <code>MAILING_LIST</code> Python list found in <code>web-ping.py</code>, in order to protect from spam the email addresses of my former co-workers that were unfortunately hard-coded in that variable.</p><p>Another place to hunt for sensible information is commit messages. These can be easily modified thanks to the <code>--msg-filter</code> option. Here is how I removed references to our internal <a href="http://trac.edgewall.org/">Trac</a> tickets:</p><pre class="brush: bash; title: ; notranslate">
$ git filter-branch --force --msg-filter 'sed &quot;s/ (see ticket:666)//g&quot;' -- --all
</pre><p>I also had to remove line returns introduced by abusive usage of Windows text editors (remember, WebPing was born in a corporate environment):</p><pre class="brush: bash; title: ; notranslate">
$ git filter-branch --force --prune-empty --tree-filter 'perl -i -pe &quot;s/\r//&quot; ./*' -- --all
</pre><p>The last useful command I use was the following, to fix author&#8217;s name and email:</p><pre class="brush: bash; title: ; notranslate">
$ git filter-branch --force --env-filter '
    if [ &quot;$GIT_AUTHOR_NAME&quot; = &quot;deldycke&quot; ]
      then
        export GIT_AUTHOR_NAME=&quot;Kevin Deldycke&quot;
        export GIT_AUTHOR_EMAIL=&quot;kevin@deldycke.com&quot;
    fi
    if [ &quot;$GIT_AUTHOR_NAME&quot; = &quot;diehr&quot; ]
      then
        export GIT_AUTHOR_NAME=&quot;Matthieu Diehr&quot;
        export GIT_AUTHOR_EMAIL=&quot;matthieu.diehr@gmail.com&quot;
    fi
  ' -- --all
</pre><p>By using a dozen variations of the commands above, and carefully reviewing the code, I was able to engineer a clean code history.</p><p>But I certainly have been a little too blunt with these regular expressions. Some of them were able to act on binary content. As a result, I <a href="http://github.com/kdeldycke/webping/commit/8c72cbee1a4f72066ffe9fa82b2b06baadca9f24">had to restore static images</a> to their original copy.</p><h2>Final steps</h2><p>Now that your code is clean, all you need is to recreate you tag and fix the <code>init</code> tag date before committing everything to GitHub:</p><pre class="brush: bash; title: ; notranslate">
$ git tag -f &quot;0.0&quot; bad4ff7fc48b8b34f6f661d75c782c7fc0d098c5
$ git tag -f &quot;0.1&quot; 590ac9953df0e3bc76fd02615471e36a9796a065
$ git tag -f &quot;0.2&quot; 33f731054042b02c6d2600e7aead5bb7c4991b12
$ git filter-branch --env-filter '
      if [ $GIT_COMMIT = 361224542bc73bba747c7ca382e992e2cdd0c356 ]
      then
          export GIT_AUTHOR_DATE=&quot;Thu, 01 Jan 1970 00:00:00 +0000&quot;
          export GIT_COMMITTER_DATE=&quot;Thu, 01 Jan 1970 00:00:00 +0000&quot;
      fi' -- --all
$ git remote add origin git@github.com:kdeldycke/webping.git
$ git push -u origin master
$ git push --tags
</pre>]]></content:encoded> <wfw:commentRss>http://kevin.deldycke.com/2011/08/how-open-source-an-internal-corporate-project-webping/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>Apache commands</title><link>http://kevin.deldycke.com/2011/01/apache-commands/</link> <comments>http://kevin.deldycke.com/2011/01/apache-commands/#comments</comments> <pubDate>Tue, 11 Jan 2011 10:53:50 +0000</pubDate> <dc:creator>Kev</dc:creator> <category><![CDATA[English]]></category> <category><![CDATA[Apache]]></category> <category><![CDATA[CLI]]></category> <category><![CDATA[Git]]></category> <category><![CDATA[HTTP]]></category> <category><![CDATA[nedstat]]></category> <category><![CDATA[Server]]></category> <category><![CDATA[Subversion]]></category> <category><![CDATA[Web]]></category><guid isPermaLink="false">http://kevin.deldycke.com/?p=2674</guid> <description><![CDATA[Hide Subversion and Git directories content (source): Disable rendering of PHP files coming from imported third party Javascript submodules (context): Redirect any request to current year sub-directory (I used this for a yearly-updated static web page): Here is my template &#8230; <a href="http://kevin.deldycke.com/2011/01/apache-commands/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description> <content:encoded><![CDATA[<ul><li>Hide Subversion and Git directories content (<a href="http://news.ycombinator.com/item?id=839016">source</a>):<pre class="brush: plain; title: ; notranslate">
RedirectMatch 404 /\.(svn|git)(/|$)
</pre></li><li>Disable rendering of PHP files coming from imported third party Javascript submodules (<a href="http://github.com/kdeldycke/cool-cavemen/blob/master/.htaccess">context</a>):<pre class="brush: plain; title: ; notranslate">
RedirectMatch 404 js-(.*)\.php$
</pre></li><li>Redirect any request to current year sub-directory (I used this for a yearly-updated static web page):<pre class="brush: plain; title: ; notranslate">
RewriteEngine on
RewriteRule !^/2010/ /2010/ [R=301,L]
</pre></li><li>Here is my template for domain-based virtual host routing:<pre class="brush: plain; title: ; notranslate">
# Setup the main website access
&lt;VirtualHost *:80&gt;
  ServerName example.com
  DocumentRoot /var/www/example
  # Add extra capabilities to let CMS like WordPress manage redirections
  &lt;Directory /var/www/example&gt;
    Options +FollowSymLinks +SymLinksIfOwnerMatch
  &lt;/Directory&gt;
&lt;/VirtualHost&gt;
# Redirect all other access to the website from different domains to the canonical URL
&lt;VirtualHost *:80&gt;
  ServerName www.example.com
  ServerAlias *.example.com
  ServerAlias example.net *.example.net
  ServerAlias example.org *.example.org
  RedirectMatch permanent (.*) http://example.com$1
&lt;/VirtualHost&gt;
</pre></li><li>Insert dynamic headers in HTTP responses depending on the browser:<pre class="brush: plain; title: ; notranslate">
BrowserMatchNoCase &quot;.*MSIE\s[1-6].*&quot; IS_DISGUSTING_BROWSER
Header add X-advice-of-the-day &quot;Save a kitten: use Firefox !&quot; env=IS_DISGUSTING_BROWSER
</pre></li><li>Prevent WebDAV connexions (thanks Guillaume!):<pre class="brush: plain; title: ; notranslate">
&lt;Location /&gt;
  &lt;Limit PROPFIND PROPPATCH MKCOL COPY MOVE LOCK UNLOCK PATCH&gt;
    # Leaves GET (and HEAD), POST, PUT, DELETE, CONNECT, OPTIONS and TRACE alone
    Order allow,deny
    Deny from all
  &lt;/Limit&gt;
&lt;/Location&gt;
SetEnvIf Request_Method &quot;OPTIONS&quot; CLIENT_PROBE
Header set Allow &quot;GET, HEAD, POST, PUT, DELETE, CONNECT, OPTIONS, TRACE&quot; env=CLIENT_PROBE
</pre></li><li>At work, we had to engineer a convoluted software architecture for our intranet to fit the network security policy of our customer. This had a bad side effect of letting the <a href="http://www.nedstat.com">web statistic collector</a> delete all cookies but its own, thus breaking intranet&#8217;s authentication. So we (thanks Matthieu!) came up with this unmaintainable hack on Apache side to hide our intranet&#8217;s cookies to NedStat&#8217;s Javascript embedded code:<pre class="brush: plain; title: ; notranslate">
&lt;LocationMatch &quot;/(.*)&quot;&gt;
  LoadModule headers_module modules/mod_headers.so
  RequestHeader edit Cookie &quot;(app_cookie_001=[^;]*(; )*)&quot; &quot;&quot;
  RequestHeader edit Cookie &quot;(app_cookie_002=[^;]*(; )*)&quot; &quot;&quot;
  RequestHeader edit Cookie &quot;(app_cookie_003=[^;]*(; )*)&quot; &quot;&quot;
&lt;/LocationMatch&gt;
</pre></li><li>Kill all apache processes and restart the service:<pre class="brush: bash; title: ; notranslate">
/etc/init.d/apache2 stop ; pkill -9 -u www-data ; /etc/init.d/apache2 restart
</pre></li><li>Restart Apache service if no process found:<pre class="brush: bash; title: ; notranslate">
[ `ps axu | grep -v &quot;grep&quot; | grep --count &quot;www-data&quot;` -le 0 ] &amp;&amp; /etc/init.d/apache2 restart
</pre></li></ul> ]]></content:encoded> <wfw:commentRss>http://kevin.deldycke.com/2011/01/apache-commands/feed/</wfw:commentRss> <slash:comments>1</slash:comments> </item> <item><title>Mercurial commands</title><link>http://kevin.deldycke.com/2010/10/mercurial-commands/</link> <comments>http://kevin.deldycke.com/2010/10/mercurial-commands/#comments</comments> <pubDate>Thu, 07 Oct 2010 11:26:53 +0000</pubDate> <dc:creator>Kev</dc:creator> <category><![CDATA[English]]></category> <category><![CDATA[CLI]]></category> <category><![CDATA[hg]]></category> <category><![CDATA[mercurial]]></category><guid isPermaLink="false">http://kevin.deldycke.com/?p=2106</guid> <description><![CDATA[Checkout a distant repository: Commit all changes locally: Push local commits to the remote repository: Apply latest changes of the remote repository to our local working copy: Align the current repository to a specific revision: Restore all changes and files &#8230; <a href="http://kevin.deldycke.com/2010/10/mercurial-commands/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description> <content:encoded><![CDATA[<ul><li>Checkout a distant repository:<pre class="brush: bash; title: ; notranslate">
hg clone http://bitbucket.org/mirror/django
</pre></li><li>Commit all changes locally:<pre class="brush: bash; title: ; notranslate">
hg commit -m &quot;Here is my commit fixing bugs.&quot;
</pre></li><li>Push local commits to the remote repository:<pre class="brush: bash; title: ; notranslate">
hg push
</pre></li><li>Apply latest changes of the remote repository to our local working copy:<pre class="brush: bash; title: ; notranslate">
hg pull
</pre></li><li>Align the current repository to a specific revision:<pre class="brush: bash; title: ; notranslate">
hg update -r 502
</pre></li><li>Restore all changes and files to the state they are in the distant repository:<pre class="brush: bash; title: ; notranslate">
hg update -C
</pre></li><li>My minimal <code>~/.hgrc</code> config file:<pre class="brush: plain; title: ; notranslate">
[ui]
username = Kevin Deldycke &lt;kevin@deldycke.com&gt;
verbose = True

[auth]
# BitBucket creds
bb.prefix = bitbucket.org
bb.username = kdeldycke
bb.password = XXXXXXXXXXX
bb.schemes = https
</pre></li><li>Display the last 5 commits:<pre class="brush: bash; title: ; notranslate">
hg log --limit 5
</pre></li><li>Display the local changes since last commit:<pre class="brush: bash; title: ; notranslate">
hg diff
</pre></li><li>Undo the last local commit:<pre class="brush: bash; title: ; notranslate">
hg rollback
</pre></li><li>Create a tag on a particular revision:<pre class="brush: bash; title: ; notranslate">
hg tag -r 432 component-2.6.1
</pre></li><li>Create a bundle file containing all changes committed locally:<pre class="brush: bash; title: ; notranslate">
hg bundle fix-bug.bundle
</pre></li></ul> ]]></content:encoded> <wfw:commentRss>http://kevin.deldycke.com/2010/10/mercurial-commands/feed/</wfw:commentRss> <slash:comments>2</slash:comments> </item> <item><title>Convert Lotus Notes&#8217; nsf files to mbox with nlconverter</title><link>http://kevin.deldycke.com/2010/09/convert-lotus-notes-nsf-files-mbox-nlconverter/</link> <comments>http://kevin.deldycke.com/2010/09/convert-lotus-notes-nsf-files-mbox-nlconverter/#comments</comments> <pubDate>Thu, 02 Sep 2010 13:17:43 +0000</pubDate> <dc:creator>Kev</dc:creator> <category><![CDATA[English]]></category> <category><![CDATA[CLI]]></category> <category><![CDATA[email]]></category> <category><![CDATA[GUI]]></category> <category><![CDATA[IBM Lotus Notes]]></category> <category><![CDATA[iCal]]></category> <category><![CDATA[mail]]></category> <category><![CDATA[mbox]]></category> <category><![CDATA[nlconverter]]></category> <category><![CDATA[Python]]></category> <category><![CDATA[Script]]></category> <category><![CDATA[windows]]></category> <category><![CDATA[Windows 2000]]></category><guid isPermaLink="false">http://kevin.deldycke.com/?p=1848</guid> <description><![CDATA[There is a great piece of software called nlconverter. It&#8217;s a tool designed to convert Lotus Notes&#8217; .nsf files to mbox. It rely on win32&#8242;s COM/DDE API so it can only be used on Windows. If you want to extract &#8230; <a href="http://kevin.deldycke.com/2010/09/convert-lotus-notes-nsf-files-mbox-nlconverter/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description> <content:encoded><![CDATA[<p>There is a great piece of software called <a href="http://code.google.com/p/nlconverter/">nlconverter</a>. It&#8217;s a tool designed to convert Lotus Notes&#8217; <code>.nsf</code> files to <code>mbox</code>. It rely on win32&#8242;s COM/DDE API so it can only be used on Windows.</p><p>If you want to extract mails out of your <code>.nsf</code> database, this might be the tool you&#8217;re looking for. Bonus point: it&#8217;s written in Python ! <img src='http://kevin.deldycke.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /></p><h2>Installing nlconverter and its dependencies</h2><p>Here is how I installed <code>nlconverter</code> on a <a href="http://www.amazon.com/gp/product/B0006HMWO4/ref=as_li_tf_tl?ie=UTF8&#038;tag=kevideld-20&#038;linkCode=as2&#038;camp=217145&#038;creative=399381&#038;creativeASIN=B0006HMWO4">Windows 2000</a> (SP4) machine:<img src="http://www.assoc-amazon.com/e/ir?t=kevideld-20&#038;l=as2&#038;o=1&#038;a=B0006HMWO4&#038;camp=217145&#038;creative=399381" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /></p><ol><li>First I downloaded and installed the <a href="http://www.python.org/download/releases/">official Python builds for Windows</a> (<a href="http://www.python.org/ftp/python/2.6.6/python-2.6.6.msi">2.6.6 precisely</a>):<br /> <a href="http://kevin.deldycke.com/wp-content/uploads/2010/08/001-python-266-install-on-windows-2000.png"><img src="http://kevin.deldycke.com/wp-content/uploads/2010/08/001-python-266-install-on-windows-2000-300x255.png" alt="" title="001-python-266-install-on-windows-2000" width="300" height="255" class="aligncenter size-medium wp-image-1832" /></a><br /> <a href="http://kevin.deldycke.com/wp-content/uploads/2010/08/002-python-266-install-on-windows-2000.png"><img src="http://kevin.deldycke.com/wp-content/uploads/2010/08/002-python-266-install-on-windows-2000-300x255.png" alt="" title="002-python-266-install-on-windows-2000" width="300" height="255" class="aligncenter size-medium wp-image-1833" /></a><br /> <a href="http://kevin.deldycke.com/wp-content/uploads/2010/08/003-python-266-install-on-windows-2000.png"><img src="http://kevin.deldycke.com/wp-content/uploads/2010/08/003-python-266-install-on-windows-2000-300x255.png" alt="" title="003-python-266-install-on-windows-2000" width="300" height="255" class="aligncenter size-medium wp-image-1834" /></a><br /> <a href="http://kevin.deldycke.com/wp-content/uploads/2010/08/004-python-266-install-on-windows-2000.png"><img src="http://kevin.deldycke.com/wp-content/uploads/2010/08/004-python-266-install-on-windows-2000-300x255.png" alt="" title="004-python-266-install-on-windows-2000" width="300" height="255" class="aligncenter size-medium wp-image-1835" /></a><br /> <a href="http://kevin.deldycke.com/wp-content/uploads/2010/08/005-python-266-install-on-windows-2000.png"><img src="http://kevin.deldycke.com/wp-content/uploads/2010/08/005-python-266-install-on-windows-2000-300x255.png" alt="" title="005-python-266-install-on-windows-2000" width="300" height="255" class="aligncenter size-medium wp-image-1836" /></a></li><li>Then <a href="http://sourceforge.net/projects/pywin32/">Python for Windows extensions</a> (<a href="http://sourceforge.net/projects/pywin32/files/pywin32/Build%20214/pywin32-214.win32-py2.6.exe/download">build 214 for Python 2.6 in my case</a>):<br /> <a href="http://kevin.deldycke.com/wp-content/uploads/2010/08/001-pywin32-214-install-on-windows-2000.png"><img src="http://kevin.deldycke.com/wp-content/uploads/2010/08/001-pywin32-214-install-on-windows-2000-300x193.png" alt="" title="001-pywin32-214-install-on-windows-2000" width="300" height="193" class="aligncenter size-medium wp-image-1838" /></a><br /> <a href="http://kevin.deldycke.com/wp-content/uploads/2010/08/002-pywin32-214-install-on-windows-2000.png"><img src="http://kevin.deldycke.com/wp-content/uploads/2010/08/002-pywin32-214-install-on-windows-2000-300x193.png" alt="" title="002-pywin32-214-install-on-windows-2000" width="300" height="193" class="aligncenter size-medium wp-image-1839" /></a><br /> <a href="http://kevin.deldycke.com/wp-content/uploads/2010/08/003-pywin32-214-install-on-windows-2000.png"><img src="http://kevin.deldycke.com/wp-content/uploads/2010/08/003-pywin32-214-install-on-windows-2000-300x193.png" alt="" title="003-pywin32-214-install-on-windows-2000" width="300" height="193" class="aligncenter size-medium wp-image-1840" /></a><br /> <a href="http://kevin.deldycke.com/wp-content/uploads/2010/08/004-pywin32-214-install-on-windows-2000.png"><img src="http://kevin.deldycke.com/wp-content/uploads/2010/08/004-pywin32-214-install-on-windows-2000-300x193.png" alt="" title="004-pywin32-214-install-on-windows-2000" width="300" height="193" class="aligncenter size-medium wp-image-1841" /></a></li><li>Finally I had to <a href="http://pypi.python.org/pypi/icalendar">download the latest <code>icalendar</code> archive</a>, then extract the <code>\iCalendar-1.2\src\icalendar</code> folder to <code>C:\Python26\Lib\site-packages\</code>:<br /> <a href="http://kevin.deldycke.com/wp-content/uploads/2010/08/extract-icalendar-python-package-on-windows.png"><img src="http://kevin.deldycke.com/wp-content/uploads/2010/08/extract-icalendar-python-package-on-windows-300x217.png" alt="" title="extract-icalendar-python-package-on-windows" width="300" height="217" class="aligncenter size-medium wp-image-1843" /></a></li><li>Next step is to <a href="http://code.google.com/p/nlconverter/downloads">download nlconverter</a> itself and extract it:<br /> <a href="http://kevin.deldycke.com/wp-content/uploads/2010/08/nlconverter-install-on-windows.png"><img src="http://kevin.deldycke.com/wp-content/uploads/2010/08/nlconverter-install-on-windows-300x214.png" alt="" title="nlconverter-install-on-windows" width="300" height="214" class="aligncenter size-medium wp-image-1846" /></a></li></ol><h2>nlconverter GUI</h2><p>First thing you have to do is to create an <a href="http://kevin.deldycke.com/2010/06/how-to-export-backup-lotus-notes-mails/">export of your mails as a <code>.nsf</code> database</a>. Follow the previous link to get the instructions.</li><p>Now let&#8217;s convert this <code>nsf</code> to a <code>mbox</code>. <a href="http://code.google.com/p/nlconverter/wiki/Faq">nlconverter&#8217;s FAQ</a> tells you to run the <code>gui.exe</code> program to perform the conversion.</p><p>Unfortunately it didn&#8217;t work for me:<br /> <a href="http://kevin.deldycke.com/wp-content/uploads/2010/08/nlconverter-gui-fail.png"><img src="http://kevin.deldycke.com/wp-content/uploads/2010/08/nlconverter-gui-fail-300x91.png" alt="" title="nlconverter-gui-fail" width="300" height="91" class="aligncenter size-medium wp-image-1856" /></a></p><p>So I tried the alternative approach by using the command line.</p><h2>nlconverter command line</h2><p>Again, most of the things I&#8217;m writing here are based on <a href="http://code.google.com/p/nlconverter/wiki/Faq">nlconverter&#8217;s FAQ</a>:</p><ol><li>First, we have to <a href="http://nlconverter.googlecode.com/hg/notes2mbox.py">download the <code>notes2mbox.py</code> script</a> from <a href="http://code.google.com/p/nlconverter/source/browse/">nlconverter&#8217;s mercurial repository</a>, as this file is not distributed in the <code>winnlc-alpha-1.zip</code> archive I unzipped previously. Let&#8217;s put <code>notes2mbox.py</code> in <code>C:\winnlc-alpha-1\</code>:<br /> <a href="http://kevin.deldycke.com/wp-content/uploads/2010/09/download-notes2mbox-python-script.png"><img src="http://kevin.deldycke.com/wp-content/uploads/2010/09/download-notes2mbox-python-script-300x167.png" alt="" title="download-notes2mbox-python-script" width="300" height="167" class="aligncenter size-medium wp-image-1881" /></a></li><li>Now we&#8217;ll modify the <code>notes2mbox.py</code> script to set the password (via the <code>notesPasswd</code> variable) and location (<code>notesNsfPath</code> variable) of the <code>.nsf</code> file. Here are the modifications I applied:<pre class="brush: diff; title: ; notranslate">
--- notes2mbox.py.orig	2010-09-02 13:49:58.000000000 +0200
+++ notes2mbox.py	2010-09-02 13:51:24.000000000 +0200
@@ -14,8 +14,8 @@
 import NlconverterLib

 #Constantes
-notesPasswd = &quot;foobar&quot;
-notesNsfPath = &quot;C:\\archive.nsf&quot;
+notesPasswd = &quot;XXXXXXXXXXXXX&quot;
+notesNsfPath = &quot;C:\\winnlc-alpha-1\\kevin-notes-big-backup-part-1.nsf&quot;

 #Connection à Notes
 db = NlconverterLib.getNotesDb(notesNsfPath, notesPasswd)
</pre></li><li>Before running the script, we have to register a Notes DLL used by nlconverter:<pre class="brush: bash; title: ; notranslate">
regsvr32 &quot;C:\Program Files\Notes\nlsxbe.dll&quot;
</pre><p><a href="http://kevin.deldycke.com/wp-content/uploads/2010/08/notes-nlsxbe-dll-registered1.png"><img src="http://kevin.deldycke.com/wp-content/uploads/2010/08/notes-nlsxbe-dll-registered1-300x96.png" alt="" title="notes-nlsxbe-dll-registered" width="300" height="96" class="aligncenter size-medium wp-image-1868" /></a><br /> And make the Python interpreter available system-wide:</p><pre class="brush: bash; title: ; notranslate">
C:\winnlc-alpha-1&gt;SET Path=%Path%;C:\Python26
</pre></li><li>Now we can run the <code>notes2mbox.py</code> script:<pre class="brush: bash; title: ; notranslate">
C:\winnlc-alpha-1&gt;C:\Python26\python.exe notes2mbox.py
</pre></li></ol><p>If you&#8217;re lucky, you&#8217;ll get a nice mbox at the end of the process.</p><p>But I was not and the <code>notes2mbox.py</code> ended up with the following error:</p><pre class="brush: python; title: ; notranslate">
Traceback (most recent call last):
  File &quot;notes2mbox.py&quot;, line 21, in &lt;module&gt;
    db = NlconverterLib.getNotesDb(notesNsfPath, notesPasswd)
  File &quot;C:\winnlc-alpha-1\NlconverterLib.py&quot;, line 43, in getNotesDb
    session = win32com.client.Dispatch(r'Lotus.NotesSession')
  File &quot;C:\Python26\lib\site-packages\win32com\client\__init__.py&quot;, line 95, in Dispatch
    dispatch, userName = dynamic._GetGoodDispatchAndUserName(dispatch,userName,clsctx)
  File &quot;C:\Python26\lib\site-packages\win32com\client\dynamic.py&quot;, line 104, in _GetGoodDispatchAndUserName
    return (_GetGoodDispatch(IDispatch, clsctx), userName)
  File &quot;C:\Python26\lib\site-packages\win32com\client\dynamic.py&quot;, line 84, in _GetGoodDispatch
    IDispatch = pythoncom.CoCreateInstance(IDispatch, None, clsctx, pythoncom.IID_IDispatch)
pywintypes.com_error: (-2147221231, 'ClassFactory ne peut pas fournir la classe demand\xe9e', None, None)
</pre><p>As you can see, I tried hard to make nlconverter working, without any success. But this should not stop you to try. In fact I suspect the Lotus Notes installed on my machine to be crippled or corrupted (can&#8217;t really tell). So you may be more lucky than me. In any case, feel free to report any success or failure in the comment section below !</p> ]]></content:encoded> <wfw:commentRss>http://kevin.deldycke.com/2010/09/convert-lotus-notes-nsf-files-mbox-nlconverter/feed/</wfw:commentRss> <slash:comments>19</slash:comments> </item> <item><title>Exim commands</title><link>http://kevin.deldycke.com/2010/07/exim-commands/</link> <comments>http://kevin.deldycke.com/2010/07/exim-commands/#comments</comments> <pubDate>Wed, 28 Jul 2010 09:54:54 +0000</pubDate> <dc:creator>Kev</dc:creator> <category><![CDATA[English]]></category> <category><![CDATA[CLI]]></category> <category><![CDATA[E-mail]]></category> <category><![CDATA[Exim]]></category> <category><![CDATA[Linux]]></category> <category><![CDATA[Mail transfer agents]]></category><guid isPermaLink="false">http://kevin.deldycke.com/?p=1617</guid> <description><![CDATA[List mails in the queue: View headers of a mail: View body of a mail: Remove a mail from the queue: Remove all frozen mails in the queue:]]></description> <content:encoded><![CDATA[<ul><li>List mails in the queue:<pre class="brush: bash; title: ; notranslate">
exim -bp
</pre></li><li>View headers of a mail:<pre class="brush: bash; title: ; notranslate">
exim -Mvh &lt;mail-id&gt;
</pre></li><li>View body of a mail:<pre class="brush: bash; title: ; notranslate">
exim -Mvb &lt;mail-id&gt;
</pre></li><li>Remove a mail from the queue:<pre class="brush: bash; title: ; notranslate">
exim -Mrm &lt;mail-id&gt;
</pre></li><li>Remove all frozen mails in the queue:<pre class="brush: bash; title: ; notranslate">
exiqgrep -z -i | xargs exim -Mrm
</pre></li></ul> ]]></content:encoded> <wfw:commentRss>http://kevin.deldycke.com/2010/07/exim-commands/feed/</wfw:commentRss> <slash:comments>2</slash:comments> </item> <item><title>Subversion commands</title><link>http://kevin.deldycke.com/2010/04/subversion-commands/</link> <comments>http://kevin.deldycke.com/2010/04/subversion-commands/#comments</comments> <pubDate>Thu, 15 Apr 2010 13:30:59 +0000</pubDate> <dc:creator>Kev</dc:creator> <category><![CDATA[English]]></category> <category><![CDATA[ack]]></category> <category><![CDATA[CLI]]></category> <category><![CDATA[find]]></category> <category><![CDATA[grep]]></category> <category><![CDATA[Linux]]></category> <category><![CDATA[sed]]></category> <category><![CDATA[shell]]></category> <category><![CDATA[Subversion]]></category><guid isPermaLink="false">http://kevin.deldycke.com/?p=1281</guid> <description><![CDATA[Native commands Revert current local folder to revision 666: Create an empty repository: Dump a repository (a sure way to migrate a subversion repository from one version to another): Migrate a remote Subversion repository without creating an intermediate dump file: &#8230; <a href="http://kevin.deldycke.com/2010/04/subversion-commands/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description> <content:encoded><![CDATA[<h2>Native commands</h2><ul><li>Revert current local folder to revision 666:<pre class="brush: bash; title: ; notranslate">
svn merge -rHEAD:666 ./
</pre></li><li>Create an empty repository:<pre class="brush: bash; title: ; notranslate">
svnadmin create ./my-repo
</pre></li><li>Dump a repository (a sure way to migrate a subversion repository from one version to another):<pre class="brush: bash; title: ; notranslate">
svnadmin dump ./my-repo &gt; ./my-repo.dmp
</pre></li><li>Migrate a remote Subversion repository without creating an intermediate dump file:<pre class="brush: bash; title: ; notranslate">
ssh -C user@myserver.com &quot;svnadmin dump /home/user/my-repo&quot; | svnadmin load /home/user2/my-new-repo
</pre></li><li>Launch a standalone Subversion server listening on port 3690 and serving all repositories located in <code>./repos/</code>:<pre class="brush: bash; title: ; notranslate">
svnserve --daemon --listen-port 3690 --root ./repos/
</pre></li></ul><h2>Local working copy hacking</h2><ul><li>Recursive and case insensitive content search on non-binary files from the current folder, while ignoring <code>.svn</code> folders and their content:<pre class="brush: bash; title: ; notranslate">
find ./ -type f -not -regex &quot;.*\/.svn\/.*&quot; -exec grep -Iil &quot;string to search&quot; {} \;
</pre></li><li>Same thing as above but with an alternative approach (that don&#8217;t work with large folder content):<pre class="brush: bash; title: ; notranslate">
grep -Ii &quot;string to search&quot; $(find . | grep -v .svn)
</pre><p>Other alternative: use <a href="http://petdance.com/ack/">ack</a>.</li><li>Use <code>sed</code> to replace text in all files except in subversion metadatas:<pre class="brush: bash; title: ; notranslate">
find ./ -type f -not -regex &quot;.*\/.svn\/.*&quot; -print -exec sed -i 's/str1/str2/g' &quot;{}&quot; \;
</pre></li><li>Use <code>svn delete</code> to remove all files containing a tilde in their name without touching local subversion metadatas:<pre class="brush: bash; title: ; notranslate">
find -type f -not -regex &quot;.*\/.svn\/.*&quot; -name &quot;*˜*&quot; -print -exec svn delete &quot;{}&quot; \;
</pre></li><li>In a repository structure containing sub-projects (thinks of <a href="https://svn.plone.org/svn/collective/">Plone&#8217;s collective repository</a> as an example), get the list of all folders in all trunks, while ignoring subversion metadata folders:<pre class="brush: bash; title: ; notranslate">
find ./ -type d -regex &quot;.*\/trunk\/?.*&quot; -not -regex &quot;.*\/.svn\/?.*&quot; -print
</pre></li><li>Similarly to the command above, replace all occurrences of the string <code>@coolcavemen.fr</code> by <code>@coolcavemen.com</code> in all <code>trunk</code> subfolders while ignoring <code>.svn</code> content:<pre class="brush: bash; title: ; notranslate">
find ./ -type f -regex &quot;.*\/trunk\/.*&quot; -not -regex &quot;.*\/.svn\/.*&quot; -print -exec sed -i 's/@coolcavemen\.fr/@coolcavemen\.com/g' &quot;{}&quot; \;
</pre></li><li>Set a svn property to ignore all <code>.mo</code> files during commit in every folder of our local working copy containing <code>.po</code> files:<pre class="brush: bash; title: ; notranslate">
find ./ -type f -name &quot;*.po&quot; -regex &quot;.*\/trunk\/.*&quot; -not -regex &quot;.*\/.svn\/.*&quot; -printf &quot;%h\n&quot; | uniq | xargs svn propset &quot;svn:ignore&quot; &quot;*.mo&quot;
</pre></li></ul> ]]></content:encoded> <wfw:commentRss>http://kevin.deldycke.com/2010/04/subversion-commands/feed/</wfw:commentRss> <slash:comments>2</slash:comments> </item> <item><title>Web commands</title><link>http://kevin.deldycke.com/2010/03/web-commands/</link> <comments>http://kevin.deldycke.com/2010/03/web-commands/#comments</comments> <pubDate>Fri, 26 Mar 2010 16:08:36 +0000</pubDate> <dc:creator>Kev</dc:creator> <category><![CDATA[English]]></category> <category><![CDATA[certificate]]></category> <category><![CDATA[CLI]]></category> <category><![CDATA[HTML]]></category> <category><![CDATA[KDE]]></category> <category><![CDATA[konqueror]]></category> <category><![CDATA[Linux]]></category> <category><![CDATA[openssl]]></category> <category><![CDATA[RSA]]></category> <category><![CDATA[ssl]]></category> <category><![CDATA[wget]]></category> <category><![CDATA[x509]]></category><guid isPermaLink="false">http://kevin.deldycke.com/?p=1257</guid> <description><![CDATA[Download a web page an all its requisites: Create a PNG image of a rendered html page: Search in all files malformed HTML entities (in this case non-breakable spaces that doesn&#8217;t end with a semicolon): Here is a one-liner I &#8230; <a href="http://kevin.deldycke.com/2010/03/web-commands/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description> <content:encoded><![CDATA[<ul><li>Download a web page an all its requisites:<pre class="brush: bash; title: ; notranslate">
wget -r -p -nc -nH --level=1 http://pypi.python.org/simple/python-ldap/
</pre></li><li>Create a PNG image of a rendered html page:<pre class="brush: bash; title: ; notranslate">
kwebdesktop 1024 768 capture.png http://slashdot.org/
</pre></li><li>Search in all files malformed HTML entities (in this case non-breakable spaces that doesn&#8217;t end with a semicolon):<pre class="brush: bash; title: ; notranslate">
grep -RIi --extended-regexp '&amp;nbsp[^;]' ./
</pre></li><li>Here is a one-liner I use to ping some pages on internet to force our corporate proxy to refresh its internal cache:<pre class="brush: bash; title: ; notranslate">
for EGG in BeautifulSoup PIL Plone; do wget --server-response -O /dev/null http://pypi.python.org/simple/$EGG/; done
</pre></li><li>Create a minimal self-signed unencrypted SSL certificate without issuer information and a validity period of 10 years:<pre class="brush: bash; title: ; notranslate">
openssl req -x509 -nodes -subj '/' -days 3650 -newkey rsa:2048 -keyout self-signed.pem -out self-signed.pem
</pre></li><li>Create a pair of SSL self-signed certificate and (unencrypted) private key (<a href="http://devsec.org/info/ssl-cert.html">source</a>):<pre class="brush: bash; title: ; notranslate">
openssl genrsa -out private.key 2048
openssl req -new -subj '/' -key private.key -out certreq.csr
openssl x509 -req -days 3650 -in certreq.csr -signkey private.key -out self-signed.pem
rm certreq.csr
</pre></li><li>View certificate details:<pre class="brush: bash; title: ; notranslate">
openssl x509 -noout -text -in self-signed.pem
</pre></li></ul> ]]></content:encoded> <wfw:commentRss>http://kevin.deldycke.com/2010/03/web-commands/feed/</wfw:commentRss> <slash:comments>4</slash:comments> </item> </channel> </rss>
<!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Minified using disk: basic
Page Caching using disk: enhanced
Database Caching 2/36 queries in 0.022 seconds using apc
Object Caching 1106/1196 objects using apc

Served from: kevin.deldycke.com @ 2012-02-08 11:22:45 -->
