don’t bash your head in: rx for shell variables.rx for shell variables. steven lembark workhorse...
TRANSCRIPT
![Page 2: Don’t BASH your head in: Rx for shell variables.Rx for shell variables. Steven Lembark Workhorse Computing lembark@wrkhors.com Quick review BASH is interpreted. Loops are re-parsed](https://reader033.vdocuments.us/reader033/viewer/2022060918/60aac67d48a0cf11411a0f38/html5/thumbnails/2.jpg)
Quick review
BASH is interpreted.
Loops are re-parsed.
Variables can appear anywhere.
Unlike Perl, Python, Ruby, Go, Haskell, Scala, Scheme,
Which separate statements from var’s.
![Page 3: Don’t BASH your head in: Rx for shell variables.Rx for shell variables. Steven Lembark Workhorse Computing lembark@wrkhors.com Quick review BASH is interpreted. Loops are re-parsed](https://reader033.vdocuments.us/reader033/viewer/2022060918/60aac67d48a0cf11411a0f38/html5/thumbnails/3.jpg)
Basic Variables
Assignments to foo:
foo=’$files’; literal ‘$files’.
![Page 4: Don’t BASH your head in: Rx for shell variables.Rx for shell variables. Steven Lembark Workhorse Computing lembark@wrkhors.com Quick review BASH is interpreted. Loops are re-parsed](https://reader033.vdocuments.us/reader033/viewer/2022060918/60aac67d48a0cf11411a0f38/html5/thumbnails/4.jpg)
Basic Variables
Assignments to foo:
foo=’$files’; literal ‘$files’.
foo=”$files”; interpolated value of files.
![Page 5: Don’t BASH your head in: Rx for shell variables.Rx for shell variables. Steven Lembark Workhorse Computing lembark@wrkhors.com Quick review BASH is interpreted. Loops are re-parsed](https://reader033.vdocuments.us/reader033/viewer/2022060918/60aac67d48a0cf11411a0f38/html5/thumbnails/5.jpg)
Basic Variables
Assignments to foo:
foo=’$files’; literal ‘$files’.
foo=”$files”; interpolated value of files.
foo=$(ls $files); command output.
![Page 6: Don’t BASH your head in: Rx for shell variables.Rx for shell variables. Steven Lembark Workhorse Computing lembark@wrkhors.com Quick review BASH is interpreted. Loops are re-parsed](https://reader033.vdocuments.us/reader033/viewer/2022060918/60aac67d48a0cf11411a0f38/html5/thumbnails/6.jpg)
Basic Variables
Assignments to foo:
foo=’$files’; literal ‘$files’.
foo=”$files”; interpolated value of files.
foo=$(ls $files); command output.
foo=”$(ls $files)”; string with listing of files.
![Page 7: Don’t BASH your head in: Rx for shell variables.Rx for shell variables. Steven Lembark Workhorse Computing lembark@wrkhors.com Quick review BASH is interpreted. Loops are re-parsed](https://reader033.vdocuments.us/reader033/viewer/2022060918/60aac67d48a0cf11411a0f38/html5/thumbnails/7.jpg)
Basic Variables
Assignments to foo:
foo=’$files’; literal ‘$files’.
foo=”$files”; interpolated value of files.
foo=$(ls $files); command output.
Most of the work is interpolating:
echo “Your files are: $(ls $somedir)”;
![Page 8: Don’t BASH your head in: Rx for shell variables.Rx for shell variables. Steven Lembark Workhorse Computing lembark@wrkhors.com Quick review BASH is interpreted. Loops are re-parsed](https://reader033.vdocuments.us/reader033/viewer/2022060918/60aac67d48a0cf11411a0f38/html5/thumbnails/8.jpg)
De-mangling variable names
> foo=’bar’;
> echo “foo$foo”; ”foobar”
> echo “$bar_foo”; “”
Oops: Variable “bar_foo” doesn’t exist.
![Page 9: Don’t BASH your head in: Rx for shell variables.Rx for shell variables. Steven Lembark Workhorse Computing lembark@wrkhors.com Quick review BASH is interpreted. Loops are re-parsed](https://reader033.vdocuments.us/reader033/viewer/2022060918/60aac67d48a0cf11411a0f38/html5/thumbnails/9.jpg)
De-mangling variable names
> foo=’bar’;
> echo “foo$foo”; ”foobar”
> echo “$bar_foo”; “”
Isolate ‘foo’ as variable name:
“${foo}_bar # “bar_bar”
![Page 10: Don’t BASH your head in: Rx for shell variables.Rx for shell variables. Steven Lembark Workhorse Computing lembark@wrkhors.com Quick review BASH is interpreted. Loops are re-parsed](https://reader033.vdocuments.us/reader033/viewer/2022060918/60aac67d48a0cf11411a0f38/html5/thumbnails/10.jpg)
Variable commands
cmd=’/bin/ls’;
arg=’-lt’;
![Page 11: Don’t BASH your head in: Rx for shell variables.Rx for shell variables. Steven Lembark Workhorse Computing lembark@wrkhors.com Quick review BASH is interpreted. Loops are re-parsed](https://reader033.vdocuments.us/reader033/viewer/2022060918/60aac67d48a0cf11411a0f38/html5/thumbnails/11.jpg)
Variable commands
cmd=’/bin/ls’;
arg=’-lt’;
files=$($cmd $arg $1); /bin/ls -lt ...
![Page 12: Don’t BASH your head in: Rx for shell variables.Rx for shell variables. Steven Lembark Workhorse Computing lembark@wrkhors.com Quick review BASH is interpreted. Loops are re-parsed](https://reader033.vdocuments.us/reader033/viewer/2022060918/60aac67d48a0cf11411a0f38/html5/thumbnails/12.jpg)
Variable commands
# interpolate each command into the loop
for i in $cmd1 $cmd2 $cmd3
do
$i $args;
done
![Page 13: Don’t BASH your head in: Rx for shell variables.Rx for shell variables. Steven Lembark Workhorse Computing lembark@wrkhors.com Quick review BASH is interpreted. Loops are re-parsed](https://reader033.vdocuments.us/reader033/viewer/2022060918/60aac67d48a0cf11411a0f38/html5/thumbnails/13.jpg)
Really anywhere!
foo=’bar’;
![Page 14: Don’t BASH your head in: Rx for shell variables.Rx for shell variables. Steven Lembark Workhorse Computing lembark@wrkhors.com Quick review BASH is interpreted. Loops are re-parsed](https://reader033.vdocuments.us/reader033/viewer/2022060918/60aac67d48a0cf11411a0f38/html5/thumbnails/14.jpg)
Really, anywhere!
foo=’bar’;
$foo=’blort’;
Q: What happens?
![Page 15: Don’t BASH your head in: Rx for shell variables.Rx for shell variables. Steven Lembark Workhorse Computing lembark@wrkhors.com Quick review BASH is interpreted. Loops are re-parsed](https://reader033.vdocuments.us/reader033/viewer/2022060918/60aac67d48a0cf11411a0f38/html5/thumbnails/15.jpg)
Really, anywhere!
foo=’bar’;
$foo=’blort’;
Q: What happens?
A: Nada.
bash: bar=blort: command not found
![Page 16: Don’t BASH your head in: Rx for shell variables.Rx for shell variables. Steven Lembark Workhorse Computing lembark@wrkhors.com Quick review BASH is interpreted. Loops are re-parsed](https://reader033.vdocuments.us/reader033/viewer/2022060918/60aac67d48a0cf11411a0f38/html5/thumbnails/16.jpg)
Your one chance at success
BASH parses in two phases:
Lexical substitution & tokenizing.
Execution.
Variables have to expand on the first pass to be used.
“foo=blort” cannot be executed, so it failed.
![Page 17: Don’t BASH your head in: Rx for shell variables.Rx for shell variables. Steven Lembark Workhorse Computing lembark@wrkhors.com Quick review BASH is interpreted. Loops are re-parsed](https://reader033.vdocuments.us/reader033/viewer/2022060918/60aac67d48a0cf11411a0f38/html5/thumbnails/17.jpg)
Verbosity & Execution
See what bash is doing with the variables:
> set -vx;
![Page 18: Don’t BASH your head in: Rx for shell variables.Rx for shell variables. Steven Lembark Workhorse Computing lembark@wrkhors.com Quick review BASH is interpreted. Loops are re-parsed](https://reader033.vdocuments.us/reader033/viewer/2022060918/60aac67d48a0cf11411a0f38/html5/thumbnails/18.jpg)
Verbosity & Execution
See what bash is doing with the variables:
> set -vx;echo -ne "\033]0;./$(basename $PWD) \007"+++ basename /sandbox/lembark/writings/RockfordLUG/bash++ echo -ne '\033]0;./bash \007'>
![Page 19: Don’t BASH your head in: Rx for shell variables.Rx for shell variables. Steven Lembark Workhorse Computing lembark@wrkhors.com Quick review BASH is interpreted. Loops are re-parsed](https://reader033.vdocuments.us/reader033/viewer/2022060918/60aac67d48a0cf11411a0f38/html5/thumbnails/19.jpg)
Verbosity & Execution
See what bash is doing with the variables:
> set -vx;echo -ne "\033]0;./$(basename $PWD) \007"+++ basename /sandbox/lembark/writings/RockfordLUG/bash++ echo -ne '\033]0;./bash \007'>
Well... sort of.
![Page 20: Don’t BASH your head in: Rx for shell variables.Rx for shell variables. Steven Lembark Workhorse Computing lembark@wrkhors.com Quick review BASH is interpreted. Loops are re-parsed](https://reader033.vdocuments.us/reader033/viewer/2022060918/60aac67d48a0cf11411a0f38/html5/thumbnails/20.jpg)
“unset” removes variables
> unset PROMPT_COMMAND;> set -vx;>
![Page 21: Don’t BASH your head in: Rx for shell variables.Rx for shell variables. Steven Lembark Workhorse Computing lembark@wrkhors.com Quick review BASH is interpreted. Loops are re-parsed](https://reader033.vdocuments.us/reader033/viewer/2022060918/60aac67d48a0cf11411a0f38/html5/thumbnails/21.jpg)
Verbosity & Execution
> unset PROMPT_COMMAND;> set -vx;> foo=bar; what I typedfoo=bar; what BASH read+ foo=bar single ‘+’ is one level deep
![Page 22: Don’t BASH your head in: Rx for shell variables.Rx for shell variables. Steven Lembark Workhorse Computing lembark@wrkhors.com Quick review BASH is interpreted. Loops are re-parsed](https://reader033.vdocuments.us/reader033/viewer/2022060918/60aac67d48a0cf11411a0f38/html5/thumbnails/22.jpg)
Verbosity & Execution
> unset PROMPT_COMMAND;> set -vx;> foo=bar; what I typedfoo=bar; what BASH read+ foo=bar single ‘+’ is one level deep> $foo='blort';>foo='blort';+ bar=blort no second chance to re-parse
![Page 23: Don’t BASH your head in: Rx for shell variables.Rx for shell variables. Steven Lembark Workhorse Computing lembark@wrkhors.com Quick review BASH is interpreted. Loops are re-parsed](https://reader033.vdocuments.us/reader033/viewer/2022060918/60aac67d48a0cf11411a0f38/html5/thumbnails/23.jpg)
Verbosity & Execution
> unset PROMPT_COMMAND;> set -vx;> foo=bar; what I typedfoo=bar; what BASH read+ foo=bar single ‘+’ is one level deep> $foo='blort';>foo='blort';+ bar=blort no second chance to re-parsebash: bar=blort: command not found
![Page 24: Don’t BASH your head in: Rx for shell variables.Rx for shell variables. Steven Lembark Workhorse Computing lembark@wrkhors.com Quick review BASH is interpreted. Loops are re-parsed](https://reader033.vdocuments.us/reader033/viewer/2022060918/60aac67d48a0cf11411a0f38/html5/thumbnails/24.jpg)
A second chance in life
‘eval’ adds one cycle.
Interpolates variables.
Passes result to the shell.
‘++’ is two levels deep.
> eval"$foo=blort";+ eval bar=blort++ bar=blort> echo $bar;+ echo blortblort
![Page 25: Don’t BASH your head in: Rx for shell variables.Rx for shell variables. Steven Lembark Workhorse Computing lembark@wrkhors.com Quick review BASH is interpreted. Loops are re-parsed](https://reader033.vdocuments.us/reader033/viewer/2022060918/60aac67d48a0cf11411a0f38/html5/thumbnails/25.jpg)
Or a third chance...
eval “eval … “;
Work out what is happening:
a=’$HOME/?.*’;
b=’foo’;
c=eval “eval $a $b”’;
![Page 26: Don’t BASH your head in: Rx for shell variables.Rx for shell variables. Steven Lembark Workhorse Computing lembark@wrkhors.com Quick review BASH is interpreted. Loops are re-parsed](https://reader033.vdocuments.us/reader033/viewer/2022060918/60aac67d48a0cf11411a0f38/html5/thumbnails/26.jpg)
Command execution
We all remember backticks:
a=`ls -al ~`’;
![Page 27: Don’t BASH your head in: Rx for shell variables.Rx for shell variables. Steven Lembark Workhorse Computing lembark@wrkhors.com Quick review BASH is interpreted. Loops are re-parsed](https://reader033.vdocuments.us/reader033/viewer/2022060918/60aac67d48a0cf11411a0f38/html5/thumbnails/27.jpg)
Command execution
We all remember backticks:
a=`ls -al ~`’;
Better off forgotten:
No way to nest them for one.
Hard to read for another.
![Page 28: Don’t BASH your head in: Rx for shell variables.Rx for shell variables. Steven Lembark Workhorse Computing lembark@wrkhors.com Quick review BASH is interpreted. Loops are re-parsed](https://reader033.vdocuments.us/reader033/viewer/2022060918/60aac67d48a0cf11411a0f38/html5/thumbnails/28.jpg)
Command execution
BASH offers a better way:
$( ... )
i.e., “interpolate subshell output”.
Output of arbitrary commands:files=$(ls ~);
jobs=$( grep ‘MHz’ /proc/cpuinfo | wc -l );
echo -e “DiskHogz:\n$(du -msx *|sort -rn|head)”;
![Page 29: Don’t BASH your head in: Rx for shell variables.Rx for shell variables. Steven Lembark Workhorse Computing lembark@wrkhors.com Quick review BASH is interpreted. Loops are re-parsed](https://reader033.vdocuments.us/reader033/viewer/2022060918/60aac67d48a0cf11411a0f38/html5/thumbnails/29.jpg)
Twisting a path with basename
basename locates input for next step.
cmd=’/image/bin/extract-hi-res’;dir=’../raw’;cd high-res || exit -1;
for i in ../low-res/culled/*;do echo “Input: ‘$i’”; $cmd $dir/$(basename $i .ppm).nef;done
![Page 30: Don’t BASH your head in: Rx for shell variables.Rx for shell variables. Steven Lembark Workhorse Computing lembark@wrkhors.com Quick review BASH is interpreted. Loops are re-parsed](https://reader033.vdocuments.us/reader033/viewer/2022060918/60aac67d48a0cf11411a0f38/html5/thumbnails/30.jpg)
Twisting a path with basename
Quotes hilite whitespace in $1.
Don’t leave home without them...
cmd=’/image/bin/extract-hi-res’;dir=’../raw’;cd high-res || exit -1;
for i in ../low-res/culled/*;do echo “Input: ‘$i’”; $cmd $dir/$(basename $i .ppm).nef;done
![Page 31: Don’t BASH your head in: Rx for shell variables.Rx for shell variables. Steven Lembark Workhorse Computing lembark@wrkhors.com Quick review BASH is interpreted. Loops are re-parsed](https://reader033.vdocuments.us/reader033/viewer/2022060918/60aac67d48a0cf11411a0f38/html5/thumbnails/31.jpg)
Being there
A “here script” is “appended from stdin”.
Double-quotish.
> perl -MCPAN -E shell <<CPAN 2>&1 | tee a;
upgrade
install Module::FromPerlVer
q
CPAN
![Page 32: Don’t BASH your head in: Rx for shell variables.Rx for shell variables. Steven Lembark Workhorse Computing lembark@wrkhors.com Quick review BASH is interpreted. Loops are re-parsed](https://reader033.vdocuments.us/reader033/viewer/2022060918/60aac67d48a0cf11411a0f38/html5/thumbnails/32.jpg)
Being there
A “here script” is “appended from stdin”.
Double-quotish, into stdin.
> perl -MCPAN -E shell <<CPAN 2>&1 | tee a;
upgrade
install Module::FromPerlVer
q
CPAN
![Page 33: Don’t BASH your head in: Rx for shell variables.Rx for shell variables. Steven Lembark Workhorse Computing lembark@wrkhors.com Quick review BASH is interpreted. Loops are re-parsed](https://reader033.vdocuments.us/reader033/viewer/2022060918/60aac67d48a0cf11411a0f38/html5/thumbnails/33.jpg)
Being there
Closing tag sends EOF (^D) to command:
> perl -MCPAN -E shell <<CPAN 2>&1 | tee a;
upgrade
install Module::FromPerlVer
CPAN
![Page 34: Don’t BASH your head in: Rx for shell variables.Rx for shell variables. Steven Lembark Workhorse Computing lembark@wrkhors.com Quick review BASH is interpreted. Loops are re-parsed](https://reader033.vdocuments.us/reader033/viewer/2022060918/60aac67d48a0cf11411a0f38/html5/thumbnails/34.jpg)
Being there
module=’Module::FromPerlVer’;
> perl -MCPAN -E shell <<CPAN 2>&1 | tee a;
upgrade
install $module
CPAN
![Page 35: Don’t BASH your head in: Rx for shell variables.Rx for shell variables. Steven Lembark Workhorse Computing lembark@wrkhors.com Quick review BASH is interpreted. Loops are re-parsed](https://reader033.vdocuments.us/reader033/viewer/2022060918/60aac67d48a0cf11411a0f38/html5/thumbnails/35.jpg)
Being there
#!/bin/bash
...
path=”$mysql_d/$tspace”;
mkdir -p $path || exit -2;
mysql -U$user -P$pass <<SQL || exit -3;
create tablespace $tspace
using ‘$path’ … ;
create table big ( … ) tablespace $tspace;
SQL
![Page 36: Don’t BASH your head in: Rx for shell variables.Rx for shell variables. Steven Lembark Workhorse Computing lembark@wrkhors.com Quick review BASH is interpreted. Loops are re-parsed](https://reader033.vdocuments.us/reader033/viewer/2022060918/60aac67d48a0cf11411a0f38/html5/thumbnails/36.jpg)
Being there
mysql -U$user -P$pass <<SQL || exit -3;
create tablespace $tspace
using ‘$path’ … ;
create table
$(cat $table-1.sql)
tablespace $tspace;
SQL
![Page 37: Don’t BASH your head in: Rx for shell variables.Rx for shell variables. Steven Lembark Workhorse Computing lembark@wrkhors.com Quick review BASH is interpreted. Loops are re-parsed](https://reader033.vdocuments.us/reader033/viewer/2022060918/60aac67d48a0cf11411a0f38/html5/thumbnails/37.jpg)
Slicing with curlies
Remove strings from the head or tail of a string.
${i#glob} ${i%glob}
${i##glob} ${i%%glob}
![Page 38: Don’t BASH your head in: Rx for shell variables.Rx for shell variables. Steven Lembark Workhorse Computing lembark@wrkhors.com Quick review BASH is interpreted. Loops are re-parsed](https://reader033.vdocuments.us/reader033/viewer/2022060918/60aac67d48a0cf11411a0f38/html5/thumbnails/38.jpg)
Slicing with curlies
Slice the head:
${i#glob}
${i##glob}
# is shortest match
## is longest match
![Page 39: Don’t BASH your head in: Rx for shell variables.Rx for shell variables. Steven Lembark Workhorse Computing lembark@wrkhors.com Quick review BASH is interpreted. Loops are re-parsed](https://reader033.vdocuments.us/reader033/viewer/2022060918/60aac67d48a0cf11411a0f38/html5/thumbnails/39.jpg)
Slicing with curlies
Slice the tail:
${i%glob}
${i%%glob}
% is shortest match
%% is longest match
![Page 40: Don’t BASH your head in: Rx for shell variables.Rx for shell variables. Steven Lembark Workhorse Computing lembark@wrkhors.com Quick review BASH is interpreted. Loops are re-parsed](https://reader033.vdocuments.us/reader033/viewer/2022060918/60aac67d48a0cf11411a0f38/html5/thumbnails/40.jpg)
Stripping a prefix.
Say you want to prefix ‘/opt/bin’ onto a PATH.
But it may already be there.
You don’t know if someone else hacked the path.
Q: How can we put ‘/opt/bin’ at the front, once?
![Page 41: Don’t BASH your head in: Rx for shell variables.Rx for shell variables. Steven Lembark Workhorse Computing lembark@wrkhors.com Quick review BASH is interpreted. Loops are re-parsed](https://reader033.vdocuments.us/reader033/viewer/2022060918/60aac67d48a0cf11411a0f38/html5/thumbnails/41.jpg)
Stripping a prefix.
Say you want to prefix ‘/opt/bin’ onto a PATH.
But it may already be there.
You don’t know if someone else hacked the path.
Q: How can we put ‘/opt/bin’ at the front, once?
A: Take it off each time.
![Page 42: Don’t BASH your head in: Rx for shell variables.Rx for shell variables. Steven Lembark Workhorse Computing lembark@wrkhors.com Quick review BASH is interpreted. Loops are re-parsed](https://reader033.vdocuments.us/reader033/viewer/2022060918/60aac67d48a0cf11411a0f38/html5/thumbnails/42.jpg)
Striptease.
‘#’ strips off leading content.
Say we tried this:
PATH=”/opt/bin:${PATH#/opt/bin:}”;
OK, I can run it a hundred times.
![Page 43: Don’t BASH your head in: Rx for shell variables.Rx for shell variables. Steven Lembark Workhorse Computing lembark@wrkhors.com Quick review BASH is interpreted. Loops are re-parsed](https://reader033.vdocuments.us/reader033/viewer/2022060918/60aac67d48a0cf11411a0f38/html5/thumbnails/43.jpg)
Path hack striptease.
‘#’ strips off leading content.
Say we tried this:
PATH=”/opt/bin:${PATH#/opt/bin:}”;
OK, I can run it a hundred times.
Until /opt/bin isn’t first:
“~/bin:/opt/bin: ...”
![Page 44: Don’t BASH your head in: Rx for shell variables.Rx for shell variables. Steven Lembark Workhorse Computing lembark@wrkhors.com Quick review BASH is interpreted. Loops are re-parsed](https://reader033.vdocuments.us/reader033/viewer/2022060918/60aac67d48a0cf11411a0f38/html5/thumbnails/44.jpg)
Globs save the day
Find everything up to the first match:
PATH=”/opt/bin:${PATH#*/opt/bin:}”;
> echo $PATH;/usr/local/bin:/usr/bin:/bin:/opt/bin:/usr/i486-pc-linux-gnu/gcc-bin/4.1.2
![Page 45: Don’t BASH your head in: Rx for shell variables.Rx for shell variables. Steven Lembark Workhorse Computing lembark@wrkhors.com Quick review BASH is interpreted. Loops are re-parsed](https://reader033.vdocuments.us/reader033/viewer/2022060918/60aac67d48a0cf11411a0f38/html5/thumbnails/45.jpg)
Globs save the day
Find everything up to the first match:
PATH=”/opt/bin:${PATH#*/opt/bin:}”;
> echo ${PATH#*/opt/bin:};+ echo /usr/local/bin:/usr/bin:/bin:/opt/bin:/usr/i486-pc-linux-gnu/gcc-bin/4.1.2
![Page 46: Don’t BASH your head in: Rx for shell variables.Rx for shell variables. Steven Lembark Workhorse Computing lembark@wrkhors.com Quick review BASH is interpreted. Loops are re-parsed](https://reader033.vdocuments.us/reader033/viewer/2022060918/60aac67d48a0cf11411a0f38/html5/thumbnails/46.jpg)
Globs save the day
Find everything up to the first match:
PATH=”/opt/bin:${PATH#*/opt/bin:}”;
> echo ${PATH#*/opt/bin:};+ echo /usr/local/bin:/usr/bin:/bin:/opt/bin:/usr/i486-pc-linux-gnu/gcc-bin/4.1.2
![Page 47: Don’t BASH your head in: Rx for shell variables.Rx for shell variables. Steven Lembark Workhorse Computing lembark@wrkhors.com Quick review BASH is interpreted. Loops are re-parsed](https://reader033.vdocuments.us/reader033/viewer/2022060918/60aac67d48a0cf11411a0f38/html5/thumbnails/47.jpg)
Globs save the day
Find everything up to the first match:
PATH=”/opt/bin:${PATH#*/opt/bin:}”;
/usr/i486-pc-linux-gnu/gcc-bin/4.1.2
![Page 48: Don’t BASH your head in: Rx for shell variables.Rx for shell variables. Steven Lembark Workhorse Computing lembark@wrkhors.com Quick review BASH is interpreted. Loops are re-parsed](https://reader033.vdocuments.us/reader033/viewer/2022060918/60aac67d48a0cf11411a0f38/html5/thumbnails/48.jpg)
Fixing the path
Takes a bit more logic:
Strip /opt/bin out of the path.
Paste it onto the front.
Globs aren’t smart enough.
![Page 49: Don’t BASH your head in: Rx for shell variables.Rx for shell variables. Steven Lembark Workhorse Computing lembark@wrkhors.com Quick review BASH is interpreted. Loops are re-parsed](https://reader033.vdocuments.us/reader033/viewer/2022060918/60aac67d48a0cf11411a0f38/html5/thumbnails/49.jpg)
Fixing the path
Takes a bit more logic:
First break up the path.
> echo $PATH | tr ':' "\n" /opt/bin/usr/local/bin/usr/bin/opt/bin/bin/usr/i486-pc-linux-gnu/gcc-bin/4.1.2
![Page 50: Don’t BASH your head in: Rx for shell variables.Rx for shell variables. Steven Lembark Workhorse Computing lembark@wrkhors.com Quick review BASH is interpreted. Loops are re-parsed](https://reader033.vdocuments.us/reader033/viewer/2022060918/60aac67d48a0cf11411a0f38/html5/thumbnails/50.jpg)
Fixing the path
Takes a bit more logic:
Then remove ‘/opt/bin’.
> echo $PATH | tr ':' "\n" | grep -v '/opt/bin' /usr/local/bin/usr/bin/bin/usr/i486-pc-linux-gnu/gcc-bin/4.1.2
![Page 51: Don’t BASH your head in: Rx for shell variables.Rx for shell variables. Steven Lembark Workhorse Computing lembark@wrkhors.com Quick review BASH is interpreted. Loops are re-parsed](https://reader033.vdocuments.us/reader033/viewer/2022060918/60aac67d48a0cf11411a0f38/html5/thumbnails/51.jpg)
Fixing the path
Takes a bit more logic:
Recombine them.
> a=$(echo $PATH | tr ':' "\n" |grep -v '/opt/bin' | tr "\n" ':');
> echo $a/usr/local/bin:/usr/bin:/bin:/usr/i486-pc-linux-gnu/gcc-bin/4.1.2::
![Page 52: Don’t BASH your head in: Rx for shell variables.Rx for shell variables. Steven Lembark Workhorse Computing lembark@wrkhors.com Quick review BASH is interpreted. Loops are re-parsed](https://reader033.vdocuments.us/reader033/viewer/2022060918/60aac67d48a0cf11411a0f38/html5/thumbnails/52.jpg)
Fixing the path
Takes a bit more logic:
Prefix ‘/opt/bin’.
> a=$(echo $PATH | tr ':' "\n" |grep -v '/opt/bin' | tr "\n" ':');
> echo “/opt/bin:$a”;/opt/bin:/usr/local/bin:/usr/bin:/bin:/usr/i486-pc-linux-gnu/gcc-bin/4.1.2::
![Page 53: Don’t BASH your head in: Rx for shell variables.Rx for shell variables. Steven Lembark Workhorse Computing lembark@wrkhors.com Quick review BASH is interpreted. Loops are re-parsed](https://reader033.vdocuments.us/reader033/viewer/2022060918/60aac67d48a0cf11411a0f38/html5/thumbnails/53.jpg)
Fixing the path
Takes a bit more logic:
Or, as a one-liner:
> PATH=\"/opt/bin:$(echo $PATH | tr ':' "\n" |grep -v '/opt/bin' | tr -s "\n" ':')";
> echo $PATH/opt/bin:/usr/local/bin:/usr/bin:/bin:/usr/i486-pc-linux-gnu/gcc-bin/4.1.2:
![Page 54: Don’t BASH your head in: Rx for shell variables.Rx for shell variables. Steven Lembark Workhorse Computing lembark@wrkhors.com Quick review BASH is interpreted. Loops are re-parsed](https://reader033.vdocuments.us/reader033/viewer/2022060918/60aac67d48a0cf11411a0f38/html5/thumbnails/54.jpg)
Quick version of basename
Strip off the longest match to ‘/’:
${file_path##*/}
Relative path within a home directory:
${file_path#$HOME}
Relative path in a sandbox directory:
${file_path##*/$(whoami)/}
![Page 55: Don’t BASH your head in: Rx for shell variables.Rx for shell variables. Steven Lembark Workhorse Computing lembark@wrkhors.com Quick review BASH is interpreted. Loops are re-parsed](https://reader033.vdocuments.us/reader033/viewer/2022060918/60aac67d48a0cf11411a0f38/html5/thumbnails/55.jpg)
Getting some tail
Clean up a directory: ${path%/}
Sandbox root: ${file%$(whoami)/*}
Root of home: ${HOME%$(whoami)*}
Less reliable dirname: ${file_path%/*}
![Page 56: Don’t BASH your head in: Rx for shell variables.Rx for shell variables. Steven Lembark Workhorse Computing lembark@wrkhors.com Quick review BASH is interpreted. Loops are re-parsed](https://reader033.vdocuments.us/reader033/viewer/2022060918/60aac67d48a0cf11411a0f38/html5/thumbnails/56.jpg)
Default values
Common use is with arguments.
> rm -rf $1/*;
What if $1 is empty?
> rm -rf /* # might not be what you want
![Page 57: Don’t BASH your head in: Rx for shell variables.Rx for shell variables. Steven Lembark Workhorse Computing lembark@wrkhors.com Quick review BASH is interpreted. Loops are re-parsed](https://reader033.vdocuments.us/reader033/viewer/2022060918/60aac67d48a0cf11411a0f38/html5/thumbnails/57.jpg)
Dealing with falsity
Common issue: Dealing with a NUL value.
Choose a default.
Assign a default.
Fail.
![Page 58: Don’t BASH your head in: Rx for shell variables.Rx for shell variables. Steven Lembark Workhorse Computing lembark@wrkhors.com Quick review BASH is interpreted. Loops are re-parsed](https://reader033.vdocuments.us/reader033/viewer/2022060918/60aac67d48a0cf11411a0f38/html5/thumbnails/58.jpg)
Use a default value
Lacking an argument, pick a value:
path=${1:-/var/tmp/input};
path=${1:-$input};
path=${1:-/var/cache/$(whoami)};
No effect on $1.
![Page 59: Don’t BASH your head in: Rx for shell variables.Rx for shell variables. Steven Lembark Workhorse Computing lembark@wrkhors.com Quick review BASH is interpreted. Loops are re-parsed](https://reader033.vdocuments.us/reader033/viewer/2022060918/60aac67d48a0cf11411a0f38/html5/thumbnails/59.jpg)
Assign a default value
Empty default assigned a value.
‘$’ interpolation may be nested:
“Default: ‘${default:=/var/tmp/$(whoami)}’”;
“:=” does not work with positional parameters ($1...).
![Page 60: Don’t BASH your head in: Rx for shell variables.Rx for shell variables. Steven Lembark Workhorse Computing lembark@wrkhors.com Quick review BASH is interpreted. Loops are re-parsed](https://reader033.vdocuments.us/reader033/viewer/2022060918/60aac67d48a0cf11411a0f38/html5/thumbnails/60.jpg)
Giving up
Maybe not providing a value is an error.
rm -rf ${path:?Path required.}/*
Code exits with “Path required.” prompt.
![Page 61: Don’t BASH your head in: Rx for shell variables.Rx for shell variables. Steven Lembark Workhorse Computing lembark@wrkhors.com Quick review BASH is interpreted. Loops are re-parsed](https://reader033.vdocuments.us/reader033/viewer/2022060918/60aac67d48a0cf11411a0f38/html5/thumbnails/61.jpg)
For example
#!/bin/bash
# if $1 has a value DEFAULT_PATH is ignored.
# empty $1 checks for non-empty default.
path=${1:-${DEFAULT_PATH:?Empty Default}};
# at this point path is not empty.
![Page 62: Don’t BASH your head in: Rx for shell variables.Rx for shell variables. Steven Lembark Workhorse Computing lembark@wrkhors.com Quick review BASH is interpreted. Loops are re-parsed](https://reader033.vdocuments.us/reader033/viewer/2022060918/60aac67d48a0cf11411a0f38/html5/thumbnails/62.jpg)
The next steps
Special Parameters:
$*, $@, $# Command line
$?, $$, $! Execution
Interpolate command line arguments, process control.
![Page 63: Don’t BASH your head in: Rx for shell variables.Rx for shell variables. Steven Lembark Workhorse Computing lembark@wrkhors.com Quick review BASH is interpreted. Loops are re-parsed](https://reader033.vdocuments.us/reader033/viewer/2022060918/60aac67d48a0cf11411a0f38/html5/thumbnails/63.jpg)
Summary
BASH interpolates variables in one pass.
${...} protect, slice variables
eval multi-pass processing.
<<TAG “here script”
-vx debugging
“Parameter Expansion” in bash(1)