<div dir="ltr">This is a great resource.  Thanks for sharing.</div><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Sep 25, 2014 at 9:23 PM,  <span dir="ltr">&lt;<a href="mailto:jep200404@columbus.rr.com" target="_blank">jep200404@columbus.rr.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">On Wed, 03 Sep 2014 20:54:48 -0400, Scott Merrill &lt;<a href="mailto:skippy@skippy.net">skippy@skippy.net</a>&gt; wrote:<br>
<br>
&gt; Jim Prior will present on editing the command line and scripting<br>
&gt; on the command line. Jim will show one or more ways of doing<br>
&gt; something, and then others will share better ways of do that same<br>
&gt; thing. This should be an interactive and pretty practical<br>
&gt; meeting.<br>
&gt;<br>
&gt;     for f in *.htm; do echo mv -i &quot;$f&quot; &quot;${f%%.htm}.html&quot;;done<br>
&gt;     for f in index.*.html; do echo mv -i &quot;$f&quot; &quot;ndx.${f##index.}&quot;;done<br>
<br>
Release early, release often.<br>
Fun was had playing around with the command line.<br>
<br>
This presentation was inspired by mailing list thread[1], which said in part:<br>
<br>
    &gt; I am no longer shocked at how many do not understand the<br>
    &gt; basic productivity enhancement tools available to them like<br>
<br>
    &gt; shell history<br>
    &gt; screen<br>
    &gt; commands like watch<br>
    &gt; in place shell programming (basic for loops, etc)<br>
<br>
and<br>
<br>
    &gt; And _most_ only know about the arrow keys for history.<br>
<br>
Of those, this presentation was about:<br>
    o   searching the history<br>
    o   editing the command line<br>
        o   loops<br>
        o   some long strings of programs piped together<br>
<br>
First a little presentation about giving presentations.<br>
<br>
    The key thing is that the presentation should be easily viewed by everyone<br>
    in the audience, including those in the back row.<br>
<br>
        Resolution<br>
<br>
            24 * 80 is about max resolution<br>
<br>
        Colors<br>
<br>
            Room lights on projection screens is common and bad, so maximize<br>
            the contrast in your content to salvage what contrast is available<br>
            to make it easier to see.<br>
<br>
            GOOD:<br>
<br>
                white on black<br>
                black on white<br>
<br>
            TOLERABLE:<br>
<br>
                pastels on white<br>
<br>
            BAD, VERY VERY BAD:<br>
<br>
                colorized text on black<br>
<br>
combining multiple commands, especially loops<br>
In the following &quot;stgfopl&quot; means something that generates filenames, one per<br>
line. Examples could include:<br>
<br>
    ls *<br>
    ls *.JPG<br>
    find . -type f -name &#39;*.pdf&#39; -print<br>
<br>
    loops<br>
<br>
        Here are some common patterns I use:<br>
<br>
            for i in `seq 1234 4566`;do echo do something with &quot;$i&quot;;done<br>
            for f in *.pdf; do echo do something with &quot;$f&quot;;done<br>
            stgfopl | while read f; do echo do something with &quot;$f&quot;;done<br>
            stgfopl | xargs some command<br>
<br>
        Most of the rest of this presentation will play with examples of those<br>
        common patterns.<br>
<br>
        I used to have loops like:<br>
<br>
            i=5;while [ $i -le 10 ]; do echo $i;i=`expr $i + 1`;done<br>
<br>
        I now usually use seq instead:<br>
<br>
            for i in `seq 5 10`;do echo $i;done<br>
<br>
        The former style still has a place where the output of seq is too much<br>
        for the shell, of if the iteration is not just simple arithmetic<br>
        sequence. For example, consider the following:<br>
<br>
            i=1;while [ $i -le `echo &#39;2^32&#39; | bc` ]; do echo $i;i=`expr $i + $i`;done<br>
<br>
        or for following links, such as in a chain of soft links, or a<br>
        linked listg.<br>
<br>
        find . -name &#39;*.pdf&#39; -print | xargs wc<br>
        find . -name &#39;*.pdf&#39; -print | while read f; do echo do something with &quot;$f&quot;;done<br>
<br>
        for i in `seq 2622 2635`; do mv -i /media/jep/disk/DCIM/100GEDSC/GEDC`printf &#39;%04d&#39; &quot;$i&quot;`.* .;done<br>
        for i in `seq 2622 2635`; do f=GEDC`printf &#39;%04d&#39; &quot;$i&quot;`.JPG;mv -i &quot;$f&quot; &quot;${f%%.JPG}.jpeg&quot; ;done<br>
<br>
            Study, compare, and contrast:<br>
<br>
                &quot;${f%%.JPG}&quot;<br>
                &quot;${f%.JPG}&quot;<br>
                &quot;${f##hello.}&quot;<br>
                &quot;${f#hello}&quot;<br>
<br>
        Some loops go on forever:<br>
<br>
            while true; do time factor 1111111111111111111;done #32-bit<br>
            while true; do time factor 11111111111111111111111111111111111111;done #64-bit<br>
            while true; do date | tr &#39;\n&#39; &#39;\r&#39;;sleep .1;done<br>
            watch -n .1 &quot;date | tr &#39;\n&#39; &#39;\r&#39;&quot;<br>
<br>
        history | sed -e &#39;s/^ *[0-9][0-9]*  [0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9] //gi&#39; | sort | uniq -c | sort -nr | head<br>
<br>
    Use echo to see what commands would be like (i.e., dry run) before actually<br>
    doing commands.<br>
<br>
        for f in *.JPG; do echo mv -i &quot;$f&quot; &quot;${f%%.JPG}.jpeg&quot; ;done<br>
        for f in *.JPG; do      mv -i &quot;$f&quot; &quot;${f%%.JPG}.jpeg&quot; ;done<br>
<br>
    classic pipelines<br>
<br>
        # Find the most common commands.<br>
        # Often there are multiple correct ways to do something.<br>
        history | awk &#39;{print $4}&#39; | sort | uniq -c | sort -n | tail<br>
        history | awk &#39;{print $4}&#39; | sort | uniq -c | sort -n | tac | head<br>
        history | awk &#39;{print $4}&#39; | sort | uniq -c | sort -nr | head<br>
<br>
        but the focus of this presentation is more complicated stuff,<br>
        particularly loops.<br>
<br>
How long of a line is too long?<br>
<br>
    If it makes your head hurt, it&#39;s too long.<br>
    If it slows you down, it&#39;s too long.<br>
    Different people tolerate different amounts of complexity.<br>
    If you&#39;re repeating some monster command often,<br>
    it might be a good candidate to put into a shell script.<br>
<br>
history options<br>
<br>
The history can have timestamps. This can help one look for an old command that<br>
one ran some time ago, by narrowing how much of the history one looks at. When<br>
developing scripts, I will often paste multiple lines from them at once. The<br>
command timestamps can document how fast things worked. Hence the following<br>
line in .bashrc.<br>
<br>
    HISTTIMEFORMAT=&quot;%F %T &quot;<br>
<br>
# Comment commands<br>
<br>
    Temporarily parking a command<br>
<br>
        In the middle of writing some command, I realize that I need to run<br>
        some other command first, so I put &#39;#&#39; at beginning of line and execute<br>
        it, so the history remembers the command I was working on. Then run the<br>
        command I needed to do first, then go back in recent history to get the<br>
        abandoned command, delete the leading # and execute it.<br>
<br>
    to document the history<br>
<br>
        Russ mentioned deliberating executing a comment command, so that it<br>
        ends up in the history to document the following (or preceding)<br>
        commands.<br>
<br>
new bash exploit<br>
<br>
    <a href="http://lists.colug.net/pipermail/colug-432/2014-September/003356.html" target="_blank">http://lists.colug.net/pipermail/colug-432/2014-September/003356.html</a><br>
    <a href="http://fedoramagazine.org/flaw-discovered-in-the-bash-shell-update-your-fedora-systems/" target="_blank">http://fedoramagazine.org/flaw-discovered-in-the-bash-shell-update-your-fedora-systems/</a><br>
    <a href="http://www.zdnet.com/unixlinux-bash-critical-security-hole-uncovered-7000034021/" target="_blank">http://www.zdnet.com/unixlinux-bash-critical-security-hole-uncovered-7000034021/</a><br>
<br>
alias lll=&#39;ls -l --full-time&#39;<br>
<br>
    The --full-time output is easier for downstream programs to sort by date<br>
    and/or time. Avoids difficulty of sorting month abbreviations. Also, the<br>
    format does not switch for files more than a year old (time of day versus<br>
    year). Compare the output of ll versus lll:<br>
<br>
    jep@presentation:~$ ll -tr /etc<br>
    total 1276<br>
    -rw-r--r--  1 root root     2064 Nov 23  2006 netscsid.conf<br>
    ...<br>
    -rw-r--r--  1 root root     1189 Sep 25 20:20 mtab<br>
    jep@presentation:~$ lll -tr /etc<br>
    total 1276<br>
    -rw-r--r--  1 root root     2064 2006-11-23 14:33:10.000000000 -0500 netscsid.conf<br>
    ...<br>
    -rw-r--r--  1 root root     1189 2014-09-25 20:20:46.194351828 -0400 mtab<br>
    jep@presentation:~$<br>
<br>
some nifty things are available in bash, but not Bourne shell<br>
avoiding them is good for portability<br>
<br>
    source instead of . (from csh, thanks Rob)<br>
<br>
    $(command) instead of `command`<br>
<br>
        $(command) can be nested.<br>
        `command` can not be nested<br>
<br>
    &gt;(command)<br>
<br>
        ... | tee &quot;$f&quot; | tee &gt;(md5sum) &gt;(sha1sum) &gt;(sha256sum) /dev/null<br>
        ... | tee &quot;$f&quot; &gt;(gzip &gt;&quot;$f&quot;.gz) &gt;(bzip2 &gt;&quot;$f&quot;.bz2) /dev/null<br>
        drive=/dev/sr0;readrawcd $drive | tee &gt;(md5sum) &gt;(sha1sum) &gt;(sha256sum) &gt;/dev/null;sleep 10;eject $drive;date<br>
        drive=xubuntu-12.04.4-desktop-i386.iso;readrawcd $drive | tee &gt;(md5sum) &gt;(sha1sum) &gt;(sha256sum) &gt;/dev/null;sleep 10;eject $drive;date<br>
<br>
        tees tease: for fun try the above tees without the /dev/null<br>
<br>
    &lt;(command)<br>
<br>
        vidf old new<br>
<br>
        jep@presentation:~$ cat ~/bin/vidf<br>
        # vim -O &quot;$1&quot; &quot;$2&quot; &lt;(diff &quot;$1&quot; &quot;$2&quot;)<br>
        vim -O &lt;(diff &quot;$1&quot; &quot;$2&quot;) &quot;$1&quot; &quot;$2&quot;<br>
        jep@presentation:~$<br>
<br>
    $((arithmetic expression)) (e.g., $(($i + 1))<br>
<br>
        i=5<br>
        echo `expr $i + 1`<br>
        echo `echo &quot;$i + 1&quot; | bc`<br>
        echo `echo &quot;print $i + 1&quot; | python`<br>
        # How to do above with awk instead of python?<br>
<br>
Miscellaneous<br>
<br>
    Begin dangerous commands with &#39;#&#39; or echo while editing them.<br>
    Remove the &#39;#&#39; or echo after one is satisfied that the command is correct.<br>
<br>
<br>
        # rm -rf / foo<br>
        # rm -rf /foo<br>
        rm -rf /foo<br>
<br>
        echo rm -rf / foo<br>
        echo rm -rf /foo<br>
        rm -rf /foo<br>
<br>
    sudo !! is handy for rerunning command with sudo<br>
<br>
        rm -rf /tmp/*<br>
        sudo !!<br>
<br>
    cmatrix text &quot;screensave&quot;<br>
<br>
        On a sacrificial Ubuntu box in an xterm:<br>
<br>
            sudo apt-get update<br>
            sudo apt-get install cmatrix<br>
            cmatrix<br>
<br>
.bashrc<br>
<br>
    Many programs pay attention to the following:<br>
<br>
        EDITOR=vim<br>
        export EDITOR<br>
<br>
    history options: I commented out some of Xubuntu&#39;s defaults.<br>
<br>
        # don&#39;t put duplicate lines or lines starting with space in the history.<br>
        # See bash(1) for more options<br>
        #HISTCONTROL=ignoreboth<br>
<br>
        # append to the history file, don&#39;t overwrite it<br>
        shopt -s histappend<br>
<br>
            Jason and Russ, please elaborate on the benefits and drawbacks of<br>
            &quot;shopt -s histappend&quot;.<br>
<br>
        # for setting history length see HISTSIZE and HISTFILESIZE in bash(1)<br>
        HISTSIZE=400000<br>
        HISTFILESIZE=400000<br>
        # HISTCONTROL=ignoredups:ignorespace<br>
<br>
            I want all commands in the history. I _do_ want to save the<br>
            duplicate commands. Sometimes repeated commands are necessary for<br>
            some task. Having the history remember the repeated commands is<br>
            helpful for repeating the whole sequence again later. Sometimes I<br>
            want to see how long each command took. Timestamps for repeated<br>
            commands answer that. My command to show the most common commands<br>
            relies upon those duplicate commands being in the<br>
            history.<br>
<br>
        unset HISTCONTROL<br>
        HISTFILESIZE=400000<br>
        HISTSIZE=400000<br>
        HISTTIMEFORMAT=&quot;%F %T &quot;<br>
        export HISTCONTROL<br>
        export HISTFILESIZE<br>
        export HISTSIZE<br>
<br>
    EMACS is default for editing command line and history.<br>
    set -o vi to select vi for editing command line<br>
<br>
git stuff<br>
<br>
    I need to use git version control more. Good candidates are:<br>
<br>
        gas price stuff<br>
        .bashrc<br>
        .vimrc<br>
        vidf<br>
<br>
    I found <a href="http://www.git-scm.com/book/en/Git-on-the-Server" target="_blank">http://www.git-scm.com/book/en/Git-on-the-Server</a> and other git<br>
    tutorials on that site to be helpful. Rebasing is cool.<br>
<br>
locate foo | xargs md5sum | sort<br>
<br>
Russ, what the line number and URL for your nasty example from<br>
<a href="https://github.com/herrold/" target="_blank">https://github.com/herrold/</a>?<br>
<br>
Is Apple&#39;s default search engine now duckduckgo, not Google anymore?<br>
Has Apple&#39;s canary disappeared?<br>
<br>
tmux<br>
<br>
    Jason, please elaborate on virtue of using ^Q.<br>
<br>
    tmux pipe-pane -o &#39;cat &gt;&gt;&#39;$PWD/tmux.output.`date +%Y%m%d-%H%M%S`<br>
<br>
Screenkey was used to show what keys were typed to edit the command line and<br>
history. Need to tweak screenkey to:<br>
<br>
    put it out of the way to waste less space on screen<br>
    make it smaller<br>
    make it persist (a log file would be nice too)<br>
<br>
    <a href="https://launchpad.net/screenkey??" target="_blank">https://launchpad.net/screenkey??</a>??<br>
<br>
    I would be happy with key logger output showing in an xterm window.<br>
<br>
# Redirect stdout and stderr with timestamping to log file.<br>
exec 1&gt; &gt;(timestamper | tee -a log) 2&gt;&amp;1<br>
<br>
jep@presentation:~$ cat /home/jep/tools/timestamper.c<br>
#include &lt;stdlib.h&gt;<br>
#include &lt;stdio.h&gt;<br>
#include &lt;unistd.h&gt;<br>
#include &lt;time.h&gt;<br>
#include &lt;sys/time.h&gt;<br>
#include &lt;string.h&gt;<br>
<br>
#define False (0)<br>
#define True (!False)<br>
<br>
typedef unsigned char flag;<br>
<br>
#define ArrayLength(x) (sizeof(x)/sizeof(*(x)))<br>
<br>
void print_timestamp(void)<br>
{<br>
    char buf[80];<br>
    int i;<br>
    struct timeval now;<br>
    struct tm *b;<br>
<br>
    gettimeofday(&amp;now,NULL);<br>
    b=localtime(&amp;now.tv_sec);<br>
    i=sprintf(buf,&quot;%04d-%02d-%02d %02d:%02d:%02d.%06d &quot;<br>
    , b-&gt;tm_year+1900<br>
    , b-&gt;tm_mon+1<br>
    , b-&gt;tm_mday<br>
    , b-&gt;tm_hour<br>
    , b-&gt;tm_min<br>
    , b-&gt;tm_sec<br>
    , (unsigned int)now.tv_usec);<br>
<br>
    write(STDOUT_FILENO,buf,i);<br>
}<br>
<br>
int main(int argc,char *argv[])<br>
{<br>
    unsigned char buf[1];<br>
    flag please_print_timestamp=True;<br>
    int i;<br>
<br>
    while ((i=read(STDIN_FILENO,buf,ArrayLength(buf)))&gt;0) {<br>
        if (please_print_timestamp) {<br>
            please_print_timestamp=False;<br>
            print_timestamp();<br>
        }<br>
        write(STDOUT_FILENO,buf,i);<br>
        if (buf[0]==&#39;\n&#39;)<br>
            please_print_timestamp=True;<br>
    }<br>
<br>
    return EXIT_SUCCESS;<br>
}<br>
jep@presentation:~/monarch/dev-code$<br>
<br>
Impedance matching:<br>
<br>
    Cracking a whip reminds me of how tsunamis can travel in fast, short, long<br>
    waves over vast stretches of deep water, then become tall waves in short<br>
    water. What&#39;s the electrical analogy to cracking whips and tsunamis? It&#39;s<br>
    probably a bunch of capacitors dumping into some tuned LC network. Hmmm.<br>
    Study microwave strip stuff. It also reminds me of Francis turbines.<br>
<br>
wp:is a prefix for wikipedia<br>
wp:Gödel, Escher, Bach<br>
<br>
[1] It got interesting, starting around here:<br>
    <a href="http://lists.colug.net/pipermail/colug-432/2014-July/003223.html" target="_blank">http://lists.colug.net/pipermail/colug-432/2014-July/003223.html</a><br>
    <a href="http://lists.colug.net/pipermail/colug-432/2014-July/003225.html" target="_blank">http://lists.colug.net/pipermail/colug-432/2014-July/003225.html</a><br>
    <a href="http://lists.colug.net/pipermail/colug-432/2014-July/thread.html#3223" target="_blank">http://lists.colug.net/pipermail/colug-432/2014-July/thread.html#3223</a><br>
<br>
_______________________________________________<br>
colug-432 mailing list<br>
<a href="mailto:colug-432@colug.net">colug-432@colug.net</a><br>
<a href="http://lists.colug.net/mailman/listinfo/colug-432" target="_blank">http://lists.colug.net/mailman/listinfo/colug-432</a><br>
</blockquote></div><br></div>