Bash basics

From wikinotes

comments

echo "hi"   # simple comment

inline comments within a multiline string

command \
    | grep -v banana  `# omit banana from result` \
    | grep -v apple   `# omit apple from result` \
    | grep -v orange  `# omit orange from result`

print

echo

echo "text"      # print text to stdout, with a newline character
echo -n "text"   # print text to stdout, without newline character

printf

printf "%s %0.2f %i" \
    "foo" "3.14159" "3.14159" #>> 'foo 3.14 3'

types

%s: abc       # string
%f: 234.123   # float
%i: 234       # integer
%d: 234       # dec(base-10) number
%x: ea        # hex(base-16) number

formatting

# alignment
%10s:  '       abc' # right aligned, width=10
%-10s: 'abc       ' # left aligned, width=10

# float precision
%0.2f: '3.14'       # 2x decimal places

'[...]' vs '[[...]]'

This is kind of frustrating, especially when starting out.

There are two types of expressions in bash, and each uses different operators.

[ 123 -eq 123 ]    # equal
[ 123 -ne 321 ]    # not equal

[ 1 -le 2 ]        # less than or equal
[ 1 -lt 2 ]        # less than

[ 2 -ge 1 ]        # greater than or equal
[ 2 -gt 1 ]        # greater than

See man test.

[[ "123" == "123" ]]  # equal
[[ "123" != "321" ]]  # not equal

[[ "ab" <= "abc" ]]   # less characters or equal
[[ "ab" <  "abc" ]]   # less characters

[[ "abc" >= "ab" ]]   # more characters or equal
[[ "abc" >  "ab" ]]   # more characters

environment variables

export PATH=/sbin:/bin:/usr/bin:/usr/sbin    # set an environment variable using 'export'
echo $PATH                                   # refer to an environment variable

run programs

This is what bash was built for. It's just glue between more powerful programs.

# run program
program arg -arg2 "blah"

# save program output to variable
var=$(program arg -arg2 "blah")

# run command from string
command="program arg -arg2 blah"
eval($command)

fork/detach/disown programs

If you start a process in a shell, that process's stdin/stdout/stderr are linked to that shell, and the process becomes a subprocess of the shell. This means that when closing the shell, it will trigger closing your subprocess.

You can use a combination of & and disown (both bash builtins) to start independent processes, similar to using fork. Previously I was using nohup, but it is linux-specific.

st & disown st   # start a new st window.

https://superuser.com/questions/178587/how-do-i-detach-a-process-from-terminal-entirely

math

integer math

expr 10 \* 5
expr 10 / 2
expr 10 + 2
expr 5 - 1

Floating point math requires an external program (but it is available on most unix systems)

result=$(echo "7 / 3" | bc -l)
echo $result
#> 2.33333333333333333333

oneliners

Bash is designed to be not just a scripting language, but a shell. You can write very simple and powerful one-liners to perform simple tasks.

for file in *.mp3;   do echo $file     ## iterate through files matching X
basename myfile.mp3 .mp3               ## strip a particular extension off a filename

for f in *.mp3; do   o = `basename $f .mp3`;   ffmpeg -i $f $o.flac;   done	## Used together, you can do simple one-liner conversions

cat EOF

echo multiline strings

cat << EOF > out.txt
line1
line2
line3
EOF
# or csh -c 'cat ...'
sudo bash -c 'cat << EOF > /etc/yum.repos.d/some-name.repo
line1
line2
line3
EOF'
# to variable
sql=$(cat <<EOF
SELECT foo, bar FROM db
WHERE foo='baz'
EOF
)