{"id":3405,"date":"2014-08-03T16:17:40","date_gmt":"2014-08-03T08:17:40","guid":{"rendered":"http:\/\/rmohan.com\/?p=3405"},"modified":"2015-04-30T12:05:17","modified_gmt":"2015-04-30T04:05:17","slug":"shell-good-reference","status":"publish","type":"post","link":"https:\/\/mohan.sg\/?p=3405","title":{"rendered":"Shell good reference"},"content":{"rendered":"<p>The Bourne shell (\/bin\/sh) is present on all Unix installations and scripts written in this language are (quite) portable; man 1 sh is a good reference.<br \/>\nBasics<\/p>\n<p>Variables and arguments<\/p>\n<p>Assign with variable=value and get content with $variable<br \/>\nMESSAGE=&#8221;Hello World&#8221; # Assign a string<br \/>\nPI=3.1415 # Assign a decimal number<br \/>\nN=8<br \/>\nTWON=`expr $N * 2` # Arithmetic expression (only integers)<br \/>\nTWON=$(($N * 2)) # Other syntax<br \/>\nTWOPI=`echo &#8220;$PI * 2&#8221; | bc -l` # Use bc for floating point operations<br \/>\nZERO=`echo &#8220;c($PI\/4)-sqrt(2)\/2&#8221; | bc -l`<br \/>\nThe command line arguments are<br \/>\n$0, $1, $2, &#8230; # $0 is the command itself<br \/>\n$# # The number of arguments<br \/>\n$* # All arguments (also $@)<br \/>\nSpecial Variables<\/p>\n<p>$$ # The current process ID<br \/>\n$? # exit status of last command<br \/>\ncommand<br \/>\nif [ $? != 0 ]; then<br \/>\necho &#8220;command failed&#8221;<br \/>\nfi<br \/>\nmypath=`pwd`<br \/>\nmypath=${mypath}\/file.txt<br \/>\necho ${mypath##*\/} # Display the filename only<br \/>\necho ${mypath%%.*} # Full path without extention<br \/>\nfoo=\/tmp\/my.dir\/filename.tar.gz<br \/>\npath = ${foo%\/*} # Full path without extention<br \/>\nvar2=${var:=string} # Use var if set, otherwise use string<br \/>\n# assign string to var and then to var2.<br \/>\nsize=$(stat -c%s &#8220;$file&#8221;) # get file size in bourne script<br \/>\nfilesize=${size:=-1}<br \/>\nConstructs<\/p>\n<p>for file in `ls`<br \/>\ndo<br \/>\necho $file<br \/>\ndone<\/p>\n<p>count=0<br \/>\nwhile [ $count -lt 5 ]; do<br \/>\necho $count<br \/>\nsleep 1<br \/>\ncount=$(($count + 1))<br \/>\ndone<\/p>\n<p>myfunction() {<br \/>\nfind . -type f -name &#8220;*.$1&#8221; -print # $1 is first argument of the function<br \/>\n}<br \/>\nmyfunction &#8220;txt&#8221;<br \/>\nGenerate a file<\/p>\n<p>MYHOME=\/home\/colin<br \/>\ncat &gt; testhome.sh &lt;&lt; _EOF<br \/>\n# All of this goes into the file testhome.sh<br \/>\nif [ -d &#8220;$MYHOME&#8221; ] ; then<br \/>\necho $MYHOME exists<br \/>\nelse<br \/>\necho $MYHOME does not exist<br \/>\nfi<br \/>\n_EOF<br \/>\nsh testhome.sh<br \/>\nBourne script example<\/p>\n<p>As a small example, the script used to create a PDF booklet from this xhtml document:<br \/>\n#!\/bin\/sh<br \/>\n# This script creates a book in pdf format ready to print on a duplex printer<br \/>\nif [ $# -ne 1 ]; then # Check the argument<br \/>\necho 1&gt;&amp;2 &#8220;Usage: $0 HtmlFile&#8221;<br \/>\nexit 1 # non zero exit if error<br \/>\nfi<\/p>\n<p>file=$1 # Assign the filename<br \/>\nfname=${file%.*} # Get the name of the file only<br \/>\nfext=${file#*.} # Get the extension of the file<\/p>\n<p>prince $file -o $fname.pdf # from www.princexml.com<br \/>\npdftops -paper A4 -noshrink $fname.pdf $fname.ps # create postscript booklet<br \/>\ncat $fname.ps |psbook|psnup -Pa4 -2 |pstops -b &#8220;2:0,1U(21cm,29.7cm)&#8221; &gt; $fname.book.ps<\/p>\n<p>ps2pdf13 -sPAPERSIZE=a4 -sAutoRotatePages=None $fname.book.ps $fname.book.pdf<br \/>\n# use #a4 and #None on Windows!<br \/>\nexit 0 # exit 0 means successful<br \/>\nSome awk commands<\/p>\n<p>Awk is useful for field stripping, like cut in a more powerful way. Search this document for other examples. See for example gnulamp.com and one-liners for awk for some nice examples.<br \/>\nawk &#8216;{ print $2, $1 }&#8217; file # Print and inverse first two columns<br \/>\nawk &#8216;{printf(&#8220;%5d : %s\\n&#8221;, NR,$0)}&#8217; file # Add line number left aligned<br \/>\nawk &#8216;{print FNR &#8220;\\t&#8221; $0}&#8217; files # Add line number right aligned<br \/>\nawk NF test.txt # remove blank lines (same as grep &#8216;.&#8217;)<br \/>\nawk &#8216;length &gt; 80&#8217; # print line longer than 80 char)<br \/>\nSome sed commands<\/p>\n<p>Here is the one liner gold minehttp:\/\/student.northpark.edu\/pemente\/sed\/sed1line.txt. And a good introduction and tutorial to sedhttp:\/\/www.grymoire.com\/Unix\/Sed.html.<br \/>\nsed &#8216;s\/string1\/string2\/g&#8217; # Replace string1 with string2<br \/>\nsed -i &#8216;s\/wroong\/wrong\/g&#8217; *.txt # Replace a recurring word with g<br \/>\nsed &#8216;s\/\\(.*\\)1\/\\12\/g&#8217; # Modify anystring1 to anystring2<br \/>\nsed &#8216;\/<\/p>\n<p>\/,\/&lt;\\\/p&gt;\/d&#8217; t.xhtml # Delete lines that start with<\/p>\n<p># and end with<\/p>\n<p>sed &#8216;\/ *#\/d; \/^ *$\/d&#8217; # Remove comments and blank lines<br \/>\nsed &#8216;s\/[ \\t]*$\/\/&#8217; # Remove trailing spaces (use tab as \\t)<br \/>\nsed &#8216;s\/^[ \\t]*\/\/;s\/[ \\t]*$\/\/&#8217; # Remove leading and trailing spaces<br \/>\nsed &#8216;s\/[^*]\/[&amp;]\/&#8217; # Enclose first char with [] top-&gt;[t]op<br \/>\nsed = file | sed &#8216;N;s\/\\n\/\\t\/&#8217; &gt; file.num # Number lines on a file<br \/>\nRegular Expressions<\/p>\n<p>Some basic regular expression useful for sed too. See Basic Regex Syntaxhttp:\/\/www.regular-expressions.info\/reference.html for a good primer.<br \/>\n[\\^$.|?*+() # special characters any other will match themselves<br \/>\n\\ # escapes special characters and treat as literal<br \/>\n* # repeat the previous item zero or more times<br \/>\n. # single character except line break characters<br \/>\n.* # match zero or more characters<br \/>\n^ # match at the start of a line\/string<br \/>\n$ # match at the end of a line\/string<br \/>\n.$ # match a single character at the end of line\/string<br \/>\n^ $ # match line with a single space<br \/>\n[^A-Z] # match any line beginning with any char from A to Z<br \/>\nSome useful commands<\/p>\n<p>The following commands are useful to include in a script or as one liners.<br \/>\nsort -t. -k1,1n -k2,2n -k3,3n -k4,4n # Sort IPv4 ip addresses<br \/>\necho &#8216;Test&#8217; | tr &#8216;[:lower:]&#8217; &#8216;[:upper:]&#8217; # Case conversion<br \/>\necho foo.bar | cut -d . -f 1 # Returns foo<br \/>\nPID=$(ps | grep script.sh | grep bin | awk &#8216;{print $1}&#8217;) # PID of a running script<br \/>\nPID=$(ps axww | grep [p]ing | awk &#8216;{print $1}&#8217;) # PID of ping (w\/o grep pid)<br \/>\nIP=$(ifconfig $INTERFACE | sed &#8216;\/.*inet addr:\/!d;s\/\/\/;s\/ .*\/\/&#8217;) # Linux<br \/>\nIP=$(ifconfig $INTERFACE | sed &#8216;\/.*inet \/!d;s\/\/\/;s\/ .*\/\/&#8217;) # FreeBSD<br \/>\nif [ `diff file1 file2 | wc -l` != 0 ]; then [&#8230;] fi # File changed?<br \/>\ncat \/etc\/master.passwd | grep -v root | grep -v \\*: | awk -F&#8221;:&#8221; \\ # Create http passwd<br \/>\n&#8216;{ printf(&#8220;%s:%s\\n&#8221;, $1, $2) }&#8217; &gt; \/usr\/local\/etc\/apache2\/passwd<\/p>\n<p>testuser=$(cat \/usr\/local\/etc\/apache2\/passwd | grep -v \\ # Check user in passwd<br \/>\nroot | grep -v \\*: | awk -F&#8221;:&#8221; &#8216;{ printf(&#8220;%s\\n&#8221;, $1) }&#8217; | grep ^user$)<br \/>\n:(){ :|:&amp; };: # bash fork bomb. Will kill your machine<br \/>\ntail +2 file &gt; file2 # remove the first line from file<br \/>\nI use this little trick to change the file extension for many files at once. For example from .cxx to .cpp. Test it first without the | sh at the end. You can also do this with the command rename if installed. Or with bash builtins.<br \/>\n# ls *.cxx | awk -F. &#8216;{print &#8220;mv &#8220;$0&#8221; &#8220;$1&#8243;.cpp&#8221;}&#8217; | sh<br \/>\n# ls *.c | sed &#8220;s\/.*\/cp &amp; &amp;.$(date &#8220;+%Y%m%d&#8221;)\/&#8221; | sh # e.g. copy *.c to *.c.20080401<br \/>\n# rename .cxx .cpp *.cxx # Rename all .cxx to cpp<br \/>\n# for i in *.cxx; do mv $i ${i%%.cxx}.cpp; done # with bash builtins<\/p>\n<p>Bourne Shell Reference:<\/p>\n<p>This file contains short tables of commonly used items in this shell. In<br \/>\nmost cases the information applies to both the Bourne shell (sh) and the<br \/>\nnewer bash shell.<\/p>\n<p>Tests (for ifs and loops) are done with [ ] or with the test command.<\/p>\n<p>Checking files:<\/p>\n<p>-r file Check if file is readable.<br \/>\n-w file Check if file is writable.<br \/>\n-x file Check if we have execute access to file.<br \/>\n-f file Check if file is an ordinary file (as opposed to a directory,<br \/>\na device special file, etc.)<br \/>\n-s file Check if file has size greater than 0.<br \/>\n-d file Check if file is a directory.<br \/>\n-e file Check if file exists. Is true even if file is a directory.<\/p>\n<p>Example:<br \/>\nif [ -s file ]<br \/>\nthen<br \/>\nsuch and such<br \/>\nfi<\/p>\n<p>Checking strings:<\/p>\n<p>s1 = s2 Check if s1 equals s2.<br \/>\ns1 != s2 Check if s1 is not equal to s2.<br \/>\n-z s1 Check if s1 has size 0.<br \/>\n-n s1 Check if s2 has nonzero size.<br \/>\ns1 Check if s1 is not the empty string.<\/p>\n<p>Example:<br \/>\nif [ $myvar = &#8220;hello&#8221; ]<br \/>\nthen<br \/>\necho &#8220;We have a match&#8221;<br \/>\nfi<\/p>\n<p>Checking numbers:<\/p>\n<p>Note that a shell variable could contain a string that represents a number.<br \/>\nIf you want to check the numerical value use one of the following:<\/p>\n<p>n1 -eq n2 Check to see if n1 equals n2.<br \/>\nn1 -ne n2 Check to see if n1 is not equal to n2.<br \/>\nn1 -lt n2 Check to see if n1 &lt; n2.<br \/>\nn1 -le n2 Check to see if n1 &lt;= n2.<br \/>\nn1 -gt n2 Check to see if n1 &gt; n2.<br \/>\nn1 -ge n2 Check to see if n1 &gt;= n2.<\/p>\n<p>Example:<br \/>\nif [ $# -gt 1 ]<br \/>\nthen<br \/>\necho &#8220;ERROR: should have 0 or 1 command-line parameters&#8221;<br \/>\nfi<\/p>\n<p>Boolean operators:<\/p>\n<p>! not<br \/>\n-a and<br \/>\n-o or<\/p>\n<p>Example:<br \/>\nif [ $num -lt 10 -o $num -gt 100 ]<br \/>\nthen<br \/>\necho &#8220;Number $num is out of range&#8221;<br \/>\nelif [ ! -w $filename ]<br \/>\nthen<br \/>\necho &#8220;Cannot write to $filename&#8221;<br \/>\nfi<\/p>\n<p>Note that ifs can be nested. For example:<br \/>\nif [ $myvar = &#8220;y&#8221; ]<br \/>\nthen<br \/>\necho &#8220;Enter count of number of items&#8221;<br \/>\nread num<br \/>\nif [ $num -le 0 ]<br \/>\nthen<br \/>\necho &#8220;Invalid count of $num was given&#8221;<br \/>\nelse<br \/>\n&#8230; do whatever &#8230;<br \/>\nfi<br \/>\nfi<\/p>\n<p>The above example also illustrates the use of read to read a string from<br \/>\nthe keyboard and place it into a shell variable. Also note that most UNIX<br \/>\ncommands return a true (nonzero) or false (0) in the shell variable status<br \/>\nto indicate whether they succeeded or not. This return value can be checked.<br \/>\nAt the command line echo $status. In a shell script use something like this:<\/p>\n<p>if grep -q shell bshellref<br \/>\nthen<br \/>\necho &#8220;true&#8221;<br \/>\nelse<br \/>\necho &#8220;false&#8221;<br \/>\nfi<\/p>\n<p>Note that -q is the quiet version of grep. It just checks whether it is true<br \/>\nthat the string shell occurs in the file bshellref. It does not print the<br \/>\nmatching lines like grep would otherwise do.<\/p>\n<p>I\/O Redirection:<\/p>\n<p>pgm &gt; file Output of pgm is redirected to file.<br \/>\npgm &lt; file Program pgm reads its input from file.<br \/>\npgm &gt;&gt; file Output of pgm is appended to file.<br \/>\npgm1 | pgm2 Output of pgm1 is piped into pgm2 as the input to pgm2.<br \/>\nn &gt; file Output from stream with descriptor n redirected to file.<br \/>\nn &gt;&gt; file Output from stream with descriptor n appended to file.<br \/>\nn &gt;&amp; m Merge output from stream n with stream m.<br \/>\nn &lt;&amp; m Merge input from stream n with stream m.<br \/>\n&lt;&lt; tag Standard input comes from here through next tag at start of line.<\/p>\n<p>Note that file descriptor 0 is normally standard input, 1 is standard output,<br \/>\nand 2 is standard error output.<\/p>\n<p>Shell Built-in Variables:<\/p>\n<p>$0 Name of this shell script itself.<br \/>\n$1 Value of first command line parameter (similarly $2, $3, etc)<br \/>\n$# In a shell script, the number of command line parameters.<br \/>\n$* All of the command line parameters.<br \/>\n$- Options given to the shell.<br \/>\n$? Return the exit status of the last command.<br \/>\n$$ Process id of script (really id of the shell running the script)<\/p>\n<p>Pattern Matching:<\/p>\n<p>* Matches 0 or more characters.<br \/>\n? Matches 1 character.<br \/>\n[AaBbCc] Example: matches any 1 char from the list.<br \/>\n[^RGB] Example: matches any 1 char not in the list.<br \/>\n[a-g] Example: matches any 1 char from this range.<\/p>\n<p>Quoting:<br \/>\n\\c Take character c literally.<br \/>\n`cmd` Run cmd and replace it in the line of code with its output.<br \/>\n&#8220;whatever&#8221; Take whatever literally, after first interpreting $, `&#8230;`, \\<br \/>\n&#8216;whatever&#8217; Take whatever absolutely literally.<\/p>\n<p>Example:<br \/>\nmatch=`ls *.bak` Puts names of .bak files into shell variable match.<br \/>\necho \\* Echos * to screen, not all filename as in: echo *<br \/>\necho &#8216;$1$2hello&#8217; Writes literally $1$2hello on screen.<br \/>\necho &#8220;$1$2hello&#8221; Writes value of parameters 1 and 2 and string hello.<\/p>\n<p>Grouping:<\/p>\n<p>Parentheses may be used for grouping, but must be preceded by backslashes<br \/>\nsince parentheses normally have a different meaning to the shell (namely<br \/>\nto run a command or commands in a subshell). For example, you might use:<\/p>\n<p>if test \\( -r $file1 -a -r $file2 \\) -o \\( -r $1 -a -r $2 \\)<br \/>\nthen<br \/>\ndo whatever<br \/>\nfi<\/p>\n<p>Case statement:<\/p>\n<p>Here is an example that looks for a match with one of the characters a, b, c.<br \/>\nIf $1 fails to match these, it always matches the * case. A case statement<br \/>\ncan also use more advanced pattern matching.<\/p>\n<p>case &#8220;$1&#8221; in<br \/>\na) cmd1 ;;<br \/>\nb) cmd2 ;;<br \/>\nc) cmd3 ;;<br \/>\n*) cmd4 ;;<br \/>\nesac<\/p>\n<p>Shell Arithmetic:<\/p>\n<p>In the original Bourne shell arithmetic is done using the expr command as in:<br \/>\nresult=`expr $1 + 2`<br \/>\nresult2=`expr $2 + $1 \/ 2`<br \/>\nresult=`expr $2 \\* 5` (note the \\ on the * symbol)<\/p>\n<p>With bash, an expression is normally enclosed using [ ] and can use the<br \/>\nfollowing operators, in order of precedence:<br \/>\n* \/ % (times, divide, remainder)<br \/>\n+ &#8211; (add, subtract)<br \/>\n&lt; &gt; &lt;= &gt;= (the obvious comparison operators)<br \/>\n== != (equal to, not equal to)<br \/>\n&amp;&amp; (logical and)<br \/>\n|| (logical or)<br \/>\n= (assignment)<br \/>\nArithmetic is done using long integers.<\/p>\n<p>Example:<br \/>\nresult=$[$1 + 3]<\/p>\n<p>In this example we take the value of the first parameter, add 3, and place<br \/>\nthe sum into result.<\/p>\n<p>Order of Interpretation:<\/p>\n<p>The bash shell carries out its various types of interpretation for each line<br \/>\nin the following order:<\/p>\n<p>brace expansion (see a reference book)<br \/>\n~ expansion (for login ids)<br \/>\nparameters (such as $1)<br \/>\nvariables (such as $var)<br \/>\ncommand substitution (Example: match=`grep DNS *` )<br \/>\narithmetic (from left to right)<br \/>\nword splitting<br \/>\npathname expansion (using *, ?, and [abc] )<\/p>\n<p>Other Shell Features:<\/p>\n<p>$var Value of shell variable var.<br \/>\n${var}abc Example: value of shell variable var with string abc appended.<br \/>\n# At start of line, indicates a comment.<br \/>\nvar=value Assign the string value to shell variable var.<br \/>\ncmd1 &amp;&amp; cmd2 Run cmd1, then if cmd1 successful run cmd2, otherwise skip.<br \/>\ncmd1 || cmd2 Run cmd1, then if cmd1 not successful run cmd2, otherwise skip.<br \/>\ncmd1; cmd2 Do cmd1 and then cmd2.<br \/>\ncmd1 &amp; cmd2 Do cmd1, start cmd2 without waiting for cmd1 to finish.<br \/>\n(cmds) Run cmds (commands) in a subshell.<\/p>\n<p>See a good reference book for information on traps, signals, exporting of<br \/>\nvariables, functions, eval, source, etc.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The Bourne shell (\/bin\/sh) is present on all Unix installations and scripts written in this language are (quite) portable; man 1 sh is a good reference. Basics<\/p>\n<p>Variables and arguments<\/p>\n<p>Assign with variable=value and get content with $variable MESSAGE=&#8221;Hello World&#8221; # Assign a string PI=3.1415 # Assign a decimal number N=8 TWON=`expr $N * 2` [&#8230;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[47],"tags":[],"_links":{"self":[{"href":"https:\/\/mohan.sg\/index.php?rest_route=\/wp\/v2\/posts\/3405"}],"collection":[{"href":"https:\/\/mohan.sg\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mohan.sg\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mohan.sg\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/mohan.sg\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=3405"}],"version-history":[{"count":3,"href":"https:\/\/mohan.sg\/index.php?rest_route=\/wp\/v2\/posts\/3405\/revisions"}],"predecessor-version":[{"id":4695,"href":"https:\/\/mohan.sg\/index.php?rest_route=\/wp\/v2\/posts\/3405\/revisions\/4695"}],"wp:attachment":[{"href":"https:\/\/mohan.sg\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3405"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mohan.sg\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=3405"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mohan.sg\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=3405"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}