{"id":6085,"date":"2021-12-06T09:02:20","date_gmt":"2021-12-06T08:02:20","guid":{"rendered":"https:\/\/speefak.spdns.de\/oss_lifestyle\/?p=6085"},"modified":"2025-03-24T19:09:49","modified_gmt":"2025-03-24T18:09:49","slug":"bashscripting-grundlagen","status":"publish","type":"post","link":"https:\/\/speefak.spdns.de\/oss_lifestyle\/bashscripting-grundlagen\/","title":{"rendered":"Bashscripting Grundlagen"},"content":{"rendered":"<hr \/>\n<h3 id=\"introduction\" class=\"-intro\" style=\"text-align: center;\"><a href=\"https:\/\/devhints.io\/bash\" target=\"_blank\" rel=\"noopener\">Original Website<\/a><\/h3>\n<hr \/>\n<p>This is a quick reference to getting started with Bash scripting.<\/p>\n<ul>\n<li><a href=\"https:\/\/learnxinyminutes.com\/docs\/bash\/\">Learn bash in y minutes<\/a> <em>(learnxinyminutes.com)<\/em><\/li>\n<li><a href=\"http:\/\/mywiki.wooledge.org\/BashGuide\">Bash Guide<\/a> <em>(mywiki.wooledge.org)<\/em><\/li>\n<\/ul>\n<h3 id=\"example\">Example<\/h3>\n<pre><code class=\"language-bash\">#!\/usr\/bin\/env bash\r\n\r\nNAME=\"John\"\r\necho \"Hello $NAME!\"\r\n<\/code><\/pre>\n<h3 id=\"variables\">Variables<\/h3>\n<pre><code class=\"language-bash\">NAME=\"John\"\r\necho $NAME\r\necho \"$NAME\"\r\necho \"${NAME}!\"\r\n<\/code><\/pre>\n<h3 id=\"string-quotes\">String quotes<\/h3>\n<pre><code class=\"language-bash\">NAME=\"John\"\r\necho \"Hi $NAME\"  #=&gt; Hi John\r\necho 'Hi $NAME'  #=&gt; Hi $NAME\r\n<\/code><\/pre>\n<h3 id=\"shell-execution\">Shell execution<\/h3>\n<pre><code class=\"language-bash\">echo \"I'm in $(pwd)\"\r\necho \"I'm in `pwd`\"\r\n# Same\r\n<\/code><\/pre>\n<p>See <a href=\"http:\/\/wiki.bash-hackers.org\/syntax\/expansion\/cmdsubst\">Command substitution<\/a><\/p>\n<h3 id=\"conditional-execution\">Conditional execution<\/h3>\n<pre><code class=\"language-bash\">git commit &amp;&amp; git push\r\ngit commit || echo \"Commit failed\"\r\n<\/code><\/pre>\n<h3 id=\"functions-example\">Functions<\/h3>\n<pre><code class=\"language-bash\">get_name() {\r\n  echo \"John\"\r\n}\r\n\r\necho \"You are $(get_name)\"\r\n<\/code><\/pre>\n<p>See: <a href=\"#functions\">Functions<\/a><\/p>\n<h3 id=\"conditionals-example\">Conditionals<\/h3>\n<pre><code class=\"language-bash\">if [[ -z \"$string\" ]]; then\r\n  echo \"String is empty\"\r\nelif [[ -n \"$string\" ]]; then\r\n  echo \"String is not empty\"\r\nfi\r\n<\/code><\/pre>\n<p>See: <a href=\"#conditionals\">Conditionals<\/a><\/p>\n<h3 id=\"strict-mode\">Strict mode<\/h3>\n<pre><code class=\"language-bash\">set -euo pipefail\r\nIFS=$'\\n\\t'\r\n<\/code><\/pre>\n<p>See: <a href=\"http:\/\/redsymbol.net\/articles\/unofficial-bash-strict-mode\/\">Unofficial bash strict mode<\/a><\/p>\n<h3 id=\"brace-expansion\">Brace expansion<\/h3>\n<pre><code class=\"language-bash\">echo {A,B}.js\r\n<\/code><\/pre>\n<table>\n<thead>\n<tr>\n<th>Expression<\/th>\n<th>Description<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>{A,B}<\/code><\/td>\n<td>Same as <code>A B<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>{A,B}.js<\/code><\/td>\n<td>Same as <code>A.js B.js<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>{1..5}<\/code><\/td>\n<td>Same as <code>1 2 3 4 5<\/code><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>See: <a href=\"http:\/\/wiki.bash-hackers.org\/syntax\/expansion\/brace\">Brace expansion<\/a><\/p>\n<h2 id=\"parameter-expansions\" class=\"-three-column\">Parameter expansions<\/h2>\n<h3 id=\"basics\">Basics<\/h3>\n<pre><code class=\"language-bash\">name=\"John\"\r\necho ${name}\r\necho ${name\/J\/j}    #=&gt; \"john\" (substitution)\r\necho ${name:0:2}    #=&gt; \"Jo\" (slicing)\r\necho ${name::2}     #=&gt; \"Jo\" (slicing)\r\necho ${name::-1}    #=&gt; \"Joh\" (slicing)\r\necho ${name:(-1)}   #=&gt; \"n\" (slicing from right)\r\necho ${name:(-2):1} #=&gt; \"h\" (slicing from right)\r\necho ${food:-Cake}  #=&gt; $food or \"Cake\"\r\n<\/code><\/pre>\n<pre><code class=\"language-bash\">length=2\r\necho ${name:0:length}  #=&gt; \"Jo\"\r\n<\/code><\/pre>\n<p>See: <a href=\"http:\/\/wiki.bash-hackers.org\/syntax\/pe\">Parameter expansion<\/a><\/p>\n<pre><code class=\"language-bash\">STR=\"\/path\/to\/foo.cpp\"\r\necho ${STR%.cpp}    # \/path\/to\/foo\r\necho ${STR%.cpp}.o  # \/path\/to\/foo.o\r\necho ${STR%\/*}      # \/path\/to\r\n\r\necho ${STR##*.}     # cpp (extension)\r\necho ${STR##*\/}     # foo.cpp (basepath)\r\n\r\necho ${STR#*\/}      # path\/to\/foo.cpp\r\necho ${STR##*\/}     # foo.cpp\r\n\r\necho ${STR\/foo\/bar} # \/path\/to\/bar.cpp\r\n<\/code><\/pre>\n<pre><code class=\"language-bash\">STR=\"Hello world\"\r\necho ${STR:6:5}   # \"world\"\r\necho ${STR: -5:5}  # \"world\"\r\n<\/code><\/pre>\n<pre><code class=\"language-bash\">SRC=\"\/path\/to\/foo.cpp\"\r\nBASE=${SRC##*\/}   #=&gt; \"foo.cpp\" (basepath)\r\nDIR=${SRC%$BASE}  #=&gt; \"\/path\/to\/\" (dirpath)\r\n<\/code><\/pre>\n<h3 id=\"substitution\">Substitution<\/h3>\n<table>\n<thead>\n<tr>\n<th>Code<\/th>\n<th>Description<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>${FOO%suffix}<\/code><\/td>\n<td>Remove suffix<\/td>\n<\/tr>\n<tr>\n<td><code>${FOO#prefix}<\/code><\/td>\n<td>Remove prefix<\/td>\n<\/tr>\n<\/tbody>\n<tbody>\n<tr>\n<td><code>${FOO%%suffix}<\/code><\/td>\n<td>Remove long suffix<\/td>\n<\/tr>\n<tr>\n<td><code>${FOO##prefix}<\/code><\/td>\n<td>Remove long prefix<\/td>\n<\/tr>\n<\/tbody>\n<tbody>\n<tr>\n<td><code>${FOO\/from\/to}<\/code><\/td>\n<td>Replace first match<\/td>\n<\/tr>\n<tr>\n<td><code>${FOO\/\/from\/to}<\/code><\/td>\n<td>Replace all<\/td>\n<\/tr>\n<\/tbody>\n<tbody>\n<tr>\n<td><code>${FOO\/%from\/to}<\/code><\/td>\n<td>Replace suffix<\/td>\n<\/tr>\n<tr>\n<td><code>${FOO\/#from\/to}<\/code><\/td>\n<td>Replace prefix<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3 id=\"comments\">Comments<\/h3>\n<pre><code class=\"language-bash\"># Single line comment\r\n<\/code><\/pre>\n<pre><code class=\"language-bash\">: '\r\nThis is a\r\nmulti line\r\ncomment\r\n'\r\n<\/code><\/pre>\n<h3 id=\"substrings\">Substrings<\/h3>\n<table>\n<thead>\n<tr>\n<th>Expression<\/th>\n<th>Description<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>${FOO:0:3}<\/code><\/td>\n<td>Substring <em>(position, length)<\/em><\/td>\n<\/tr>\n<tr>\n<td><code>${FOO:(-3):3}<\/code><\/td>\n<td>Substring from the right<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3 id=\"length\">Length<\/h3>\n<table>\n<thead>\n<tr>\n<th>Expression<\/th>\n<th>Description<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>${#FOO}<\/code><\/td>\n<td>Length of <code>$FOO<\/code><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3 id=\"manipulation\">Manipulation<\/h3>\n<pre><code class=\"language-bash\">STR=\"HELLO WORLD!\"\r\necho ${STR,}   #=&gt; \"hELLO WORLD!\" (lowercase 1st letter)\r\necho ${STR,,}  #=&gt; \"hello world!\" (all lowercase)\r\n\r\nSTR=\"hello world!\"\r\necho ${STR^}   #=&gt; \"Hello world!\" (uppercase 1st letter)\r\necho ${STR^^}  #=&gt; \"HELLO WORLD!\" (all uppercase)\r\n<\/code><\/pre>\n<h3 id=\"default-values\">Default values<\/h3>\n<table>\n<thead>\n<tr>\n<th>Expression<\/th>\n<th>Description<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>${FOO:-val}<\/code><\/td>\n<td><code>$FOO<\/code>, or <code>val<\/code> if unset (or null)<\/td>\n<\/tr>\n<tr>\n<td><code>${FOO:=val}<\/code><\/td>\n<td>Set <code>$FOO<\/code> to <code>val<\/code> if unset (or null)<\/td>\n<\/tr>\n<tr>\n<td><code>${FOO:+val}<\/code><\/td>\n<td><code>val<\/code> if <code>$FOO<\/code> is set (and not null)<\/td>\n<\/tr>\n<tr>\n<td><code>${FOO:?message}<\/code><\/td>\n<td>Show error message and exit if <code>$FOO<\/code> is unset (or null)<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Omitting the <code>:<\/code> removes the (non)nullity checks, e.g. <code>${FOO-val}<\/code> expands to <code>val<\/code> if unset otherwise <code>$FOO<\/code>.<\/p>\n<h2 id=\"loops\" class=\"-three-column\">Loops<\/h2>\n<h3 id=\"basic-for-loop\">Basic for loop<\/h3>\n<pre><code class=\"language-bash\">for i in \/etc\/rc.*; do\r\n  echo $i\r\ndone\r\n<\/code><\/pre>\n<h3 id=\"c-like-for-loop\">C-like for loop<\/h3>\n<pre><code class=\"language-bash\">for ((i = 0 ; i &lt; 100 ; i++)); do\r\n  echo $i\r\ndone\r\n<\/code><\/pre>\n<h3 id=\"ranges\">Ranges<\/h3>\n<pre><code class=\"language-bash\">for i in {1..5}; do\r\n    echo \"Welcome $i\"\r\ndone\r\n<\/code><\/pre>\n<h4 id=\"with-step-size\">With step size<\/h4>\n<pre><code class=\"language-bash\">for i in {5..50..5}; do\r\n    echo \"Welcome $i\"\r\ndone\r\n<\/code><\/pre>\n<h3 id=\"reading-lines\">Reading lines<\/h3>\n<pre><code class=\"language-bash\">cat file.txt | while read line; do\r\n  echo $line\r\ndone\r\n<\/code><\/pre>\n<h3 id=\"forever\">Forever<\/h3>\n<pre><code class=\"language-bash\">while true; do\r\n  \u00b7\u00b7\u00b7\r\ndone\r\n<\/code><\/pre>\n<h2 id=\"functions\" class=\"-three-column\">Functions<\/h2>\n<h3 id=\"defining-functions\">Defining functions<\/h3>\n<pre><code class=\"language-bash\">myfunc() {\r\n    echo \"hello $1\"\r\n}\r\n<\/code><\/pre>\n<pre><code class=\"language-bash\"># Same as above (alternate syntax)\r\nfunction myfunc() {\r\n    echo \"hello $1\"\r\n}\r\n<\/code><\/pre>\n<pre><code class=\"language-bash\">myfunc \"John\"\r\n<\/code><\/pre>\n<h3 id=\"returning-values\">Returning values<\/h3>\n<pre><code class=\"language-bash\">myfunc() {\r\n    local myresult='some value'\r\n    echo $myresult\r\n}\r\n<\/code><\/pre>\n<pre><code class=\"language-bash\">result=\"$(myfunc)\"\r\n<\/code><\/pre>\n<h3 id=\"raising-errors\">Raising errors<\/h3>\n<pre><code class=\"language-bash\">myfunc() {\r\n  return 1\r\n}\r\n<\/code><\/pre>\n<pre><code class=\"language-bash\">if myfunc; then\r\n  echo \"success\"\r\nelse\r\n  echo \"failure\"\r\nfi\r\n<\/code><\/pre>\n<h3 id=\"arguments\">Arguments<\/h3>\n<table>\n<thead>\n<tr>\n<th>Expression<\/th>\n<th>Description<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>$#<\/code><\/td>\n<td>Number of arguments<\/td>\n<\/tr>\n<tr>\n<td><code>$*<\/code><\/td>\n<td>All positional arguments (as a single word)<\/td>\n<\/tr>\n<tr>\n<td><code>$@<\/code><\/td>\n<td>All positional arguments (as separate strings)<\/td>\n<\/tr>\n<tr>\n<td><code>$1<\/code><\/td>\n<td>First argument<\/td>\n<\/tr>\n<tr>\n<td><code>$_<\/code><\/td>\n<td>Last argument of the previous command<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><strong>Note<\/strong>: <code>$@<\/code> and <code>$*<\/code> must be quoted in order to perform as described.<br \/>\nOtherwise, they do exactly the same thing (arguments as separate strings).<\/p>\n<p>See <a href=\"http:\/\/wiki.bash-hackers.org\/syntax\/shellvars#special_parameters_and_shell_variables\">Special parameters<\/a>.<\/p>\n<h2 id=\"conditionals\" class=\"-three-column\">Conditionals<\/h2>\n<h3 id=\"conditions\">Conditions<\/h3>\n<p>Note that <code>[[<\/code> is actually a command\/program that returns either <code>0<\/code> (true) or <code>1<\/code> (false). Any program that obeys the same logic (like all base utils, such as <code>grep(1)<\/code> or <code>ping(1)<\/code>) can be used as condition, see examples.<\/p>\n<table>\n<thead>\n<tr>\n<th>Condition<\/th>\n<th>Description<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>[[ -z STRING ]]<\/code><\/td>\n<td>Empty string<\/td>\n<\/tr>\n<tr>\n<td><code>[[ -n STRING ]]<\/code><\/td>\n<td>Not empty string<\/td>\n<\/tr>\n<tr>\n<td><code>[[ STRING == STRING ]]<\/code><\/td>\n<td>Equal<\/td>\n<\/tr>\n<tr>\n<td><code>[[ STRING != STRING ]]<\/code><\/td>\n<td>Not Equal<\/td>\n<\/tr>\n<\/tbody>\n<tbody>\n<tr>\n<td><code>[[ NUM -eq NUM ]]<\/code><\/td>\n<td>Equal<\/td>\n<\/tr>\n<tr>\n<td><code>[[ NUM -ne NUM ]]<\/code><\/td>\n<td>Not equal<\/td>\n<\/tr>\n<tr>\n<td><code>[[ NUM -lt NUM ]]<\/code><\/td>\n<td>Less than<\/td>\n<\/tr>\n<tr>\n<td><code>[[ NUM -le NUM ]]<\/code><\/td>\n<td>Less than or equal<\/td>\n<\/tr>\n<tr>\n<td><code>[[ NUM -gt NUM ]]<\/code><\/td>\n<td>Greater than<\/td>\n<\/tr>\n<tr>\n<td><code>[[ NUM -ge NUM ]]<\/code><\/td>\n<td>Greater than or equal<\/td>\n<\/tr>\n<\/tbody>\n<tbody>\n<tr>\n<td><code>[[ STRING =~ STRING ]]<\/code><\/td>\n<td>Regexp<\/td>\n<\/tr>\n<\/tbody>\n<tbody>\n<tr>\n<td><code>(( NUM &lt; NUM ))<\/code><\/td>\n<td>Numeric conditions<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h4 id=\"more-conditions\">More conditions<\/h4>\n<table>\n<thead>\n<tr>\n<th>Condition<\/th>\n<th>Description<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>[[ -o noclobber ]]<\/code><\/td>\n<td>If OPTIONNAME is enabled<\/td>\n<\/tr>\n<\/tbody>\n<tbody>\n<tr>\n<td><code>[[ ! EXPR ]]<\/code><\/td>\n<td>Not<\/td>\n<\/tr>\n<tr>\n<td><code>[[ X &amp;&amp; Y ]]<\/code><\/td>\n<td>And<\/td>\n<\/tr>\n<tr>\n<td><code>[[ X || Y ]]<\/code><\/td>\n<td>Or<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3 id=\"file-conditions\">File conditions<\/h3>\n<table>\n<thead>\n<tr>\n<th>Condition<\/th>\n<th>Description<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>[[ -e FILE ]]<\/code><\/td>\n<td>Exists<\/td>\n<\/tr>\n<tr>\n<td><code>[[ -r FILE ]]<\/code><\/td>\n<td>Readable<\/td>\n<\/tr>\n<tr>\n<td><code>[[ -h FILE ]]<\/code><\/td>\n<td>Symlink<\/td>\n<\/tr>\n<tr>\n<td><code>[[ -d FILE ]]<\/code><\/td>\n<td>Directory<\/td>\n<\/tr>\n<tr>\n<td><code>[[ -w FILE ]]<\/code><\/td>\n<td>Writable<\/td>\n<\/tr>\n<tr>\n<td><code>[[ -s FILE ]]<\/code><\/td>\n<td>Size is &gt; 0 bytes<\/td>\n<\/tr>\n<tr>\n<td><code>[[ -f FILE ]]<\/code><\/td>\n<td>File<\/td>\n<\/tr>\n<tr>\n<td><code>[[ -x FILE ]]<\/code><\/td>\n<td>Executable<\/td>\n<\/tr>\n<\/tbody>\n<tbody>\n<tr>\n<td><code>[[ FILE1 -nt FILE2 ]]<\/code><\/td>\n<td>1 is more recent than 2<\/td>\n<\/tr>\n<tr>\n<td><code>[[ FILE1 -ot FILE2 ]]<\/code><\/td>\n<td>2 is more recent than 1<\/td>\n<\/tr>\n<tr>\n<td><code>[[ FILE1 -ef FILE2 ]]<\/code><\/td>\n<td>Same files<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3 id=\"example-1\">Example<\/h3>\n<pre><code class=\"language-bash\"># String\r\nif [[ -z \"$string\" ]]; then\r\n  echo \"String is empty\"\r\nelif [[ -n \"$string\" ]]; then\r\n  echo \"String is not empty\"\r\nelse\r\n  echo \"This never happens\"\r\nfi\r\n<\/code><\/pre>\n<pre><code class=\"language-bash\"># Combinations\r\nif [[ X &amp;&amp; Y ]]; then\r\n  ...\r\nfi\r\n<\/code><\/pre>\n<pre><code class=\"language-bash\"># Equal\r\nif [[ \"$A\" == \"$B\" ]]\r\n<\/code><\/pre>\n<pre><code class=\"language-bash\"># Regex\r\nif [[ \"A\" =~ . ]]\r\n<\/code><\/pre>\n<pre><code class=\"language-bash\">if (( $a &lt; $b )); then\r\n   echo \"$a is smaller than $b\"\r\nfi\r\n<\/code><\/pre>\n<pre><code class=\"language-bash\">if [[ -e \"file.txt\" ]]; then\r\n  echo \"file exists\"\r\nfi\r\n<\/code><\/pre>\n<h2 id=\"arrays\">Arrays<\/h2>\n<h3 id=\"defining-arrays\">Defining arrays<\/h3>\n<pre><code class=\"language-bash\">Fruits=('Apple' 'Banana' 'Orange')\r\n<\/code><\/pre>\n<pre><code class=\"language-bash\">Fruits[0]=\"Apple\"\r\nFruits[1]=\"Banana\"\r\nFruits[2]=\"Orange\"\r\n<\/code><\/pre>\n<h3 id=\"working-with-arrays\">Working with arrays<\/h3>\n<pre><code class=\"language-bash\">echo ${Fruits[0]}           # Element #0\r\necho ${Fruits[-1]}          # Last element\r\necho ${Fruits[@]}           # All elements, space-separated\r\necho ${#Fruits[@]}          # Number of elements\r\necho ${#Fruits}             # String length of the 1st element\r\necho ${#Fruits[3]}          # String length of the Nth element\r\necho ${Fruits[@]:3:2}       # Range (from position 3, length 2)\r\necho ${!Fruits[@]}          # Keys of all elements, space-separated\r\n<\/code><\/pre>\n<h3 id=\"operations\">Operations<\/h3>\n<pre><code class=\"language-bash\">Fruits=(\"${Fruits[@]}\" \"Watermelon\")    # Push\r\nFruits+=('Watermelon')                  # Also Push\r\nFruits=( ${Fruits[@]\/Ap*\/} )            # Remove by regex match\r\nunset Fruits[2]                         # Remove one item\r\nFruits=(\"${Fruits[@]}\")                 # Duplicate\r\nFruits=(\"${Fruits[@]}\" \"${Veggies[@]}\") # Concatenate\r\nlines=(`cat \"logfile\"`)                 # Read from file\r\n<\/code><\/pre>\n<h3 id=\"iteration\">Iteration<\/h3>\n<pre><code class=\"language-bash\">for i in \"${arrayName[@]}\"; do\r\n  echo $i\r\ndone\r\n<\/code><\/pre>\n<h2 id=\"dictionaries\" class=\"-three-column\">Dictionaries<\/h2>\n<h3 id=\"defining\">Defining<\/h3>\n<pre><code class=\"language-bash\">declare -A sounds\r\n<\/code><\/pre>\n<pre><code class=\"language-bash\">sounds[dog]=\"bark\"\r\nsounds[cow]=\"moo\"\r\nsounds[bird]=\"tweet\"\r\nsounds[wolf]=\"howl\"\r\n<\/code><\/pre>\n<p>Declares <code>sound<\/code> as a Dictionary object (aka associative array).<\/p>\n<h3 id=\"working-with-dictionaries\">Working with dictionaries<\/h3>\n<pre><code class=\"language-bash\">echo ${sounds[dog]} # Dog's sound\r\necho ${sounds[@]}   # All values\r\necho ${!sounds[@]}  # All keys\r\necho ${#sounds[@]}  # Number of elements\r\nunset sounds[dog]   # Delete dog\r\n<\/code><\/pre>\n<h3 id=\"iteration-1\">Iteration<\/h3>\n<h4 id=\"iterate-over-values\">Iterate over values<\/h4>\n<pre><code class=\"language-bash\">for val in \"${sounds[@]}\"; do\r\n  echo $val\r\ndone\r\n<\/code><\/pre>\n<h4 id=\"iterate-over-keys\">Iterate over keys<\/h4>\n<pre><code class=\"language-bash\">for key in \"${!sounds[@]}\"; do\r\n  echo $key\r\ndone\r\n<\/code><\/pre>\n<h2 id=\"options\">Options<\/h2>\n<h3 id=\"options-1\">Options<\/h3>\n<pre><code class=\"language-bash\">set -o noclobber  # Avoid overlay files (echo \"hi\" &gt; foo)\r\nset -o errexit    # Used to exit upon error, avoiding cascading errors\r\nset -o pipefail   # Unveils hidden failures\r\nset -o nounset    # Exposes unset variables\r\n<\/code><\/pre>\n<h3 id=\"glob-options\">Glob options<\/h3>\n<pre><code class=\"language-bash\">shopt -s nullglob    # Non-matching globs are removed  ('*.foo' =&gt; '')\r\nshopt -s failglob    # Non-matching globs throw errors\r\nshopt -s nocaseglob  # Case insensitive globs\r\nshopt -s dotglob     # Wildcards match dotfiles (\"*.sh\" =&gt; \".foo.sh\")\r\nshopt -s globstar    # Allow ** for recursive matches ('lib\/**\/*.rb' =&gt; 'lib\/a\/b\/c.rb')\r\n<\/code><\/pre>\n<p>Set <code>GLOBIGNORE<\/code> as a colon-separated list of patterns to be removed from glob<br \/>\nmatches.<\/p>\n<h2 id=\"history\">History<\/h2>\n<h3 id=\"commands\">Commands<\/h3>\n<table>\n<thead>\n<tr>\n<th>Command<\/th>\n<th>Description<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>history<\/code><\/td>\n<td>Show history<\/td>\n<\/tr>\n<tr>\n<td><code>shopt -s histverify<\/code><\/td>\n<td>Don\u2019t execute expanded result immediately<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3 id=\"expansions\">Expansions<\/h3>\n<table>\n<thead>\n<tr>\n<th>Expression<\/th>\n<th>Description<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>!$<\/code><\/td>\n<td>Expand last parameter of most recent command<\/td>\n<\/tr>\n<tr>\n<td><code>!*<\/code><\/td>\n<td>Expand all parameters of most recent command<\/td>\n<\/tr>\n<tr>\n<td><code>!-n<\/code><\/td>\n<td>Expand <code>n<\/code>th most recent command<\/td>\n<\/tr>\n<tr>\n<td><code>!n<\/code><\/td>\n<td>Expand <code>n<\/code>th command in history<\/td>\n<\/tr>\n<tr>\n<td><code>!&lt;command&gt;<\/code><\/td>\n<td>Expand most recent invocation of command <code>&lt;command&gt;<\/code><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3 id=\"operations-1\">Operations<\/h3>\n<table>\n<thead>\n<tr>\n<th>Code<\/th>\n<th>Description<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>!!<\/code><\/td>\n<td>Execute last command again<\/td>\n<\/tr>\n<tr>\n<td><code>!!:s\/&lt;FROM&gt;\/&lt;TO&gt;\/<\/code><\/td>\n<td>Replace first occurrence of <code>&lt;FROM&gt;<\/code> to <code>&lt;TO&gt;<\/code> in most recent command<\/td>\n<\/tr>\n<tr>\n<td><code>!!:gs\/&lt;FROM&gt;\/&lt;TO&gt;\/<\/code><\/td>\n<td>Replace all occurrences of <code>&lt;FROM&gt;<\/code> to <code>&lt;TO&gt;<\/code> in most recent command<\/td>\n<\/tr>\n<tr>\n<td><code>!$:t<\/code><\/td>\n<td>Expand only basename from last parameter of most recent command<\/td>\n<\/tr>\n<tr>\n<td><code>!$:h<\/code><\/td>\n<td>Expand only directory from last parameter of most recent command<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><code>!!<\/code> and <code>!$<\/code> can be replaced with any valid expansion.<\/p>\n<h3 id=\"slices\">Slices<\/h3>\n<table>\n<thead>\n<tr>\n<th>Code<\/th>\n<th>Description<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>!!:n<\/code><\/td>\n<td>Expand only <code>n<\/code>th token from most recent command (command is <code>0<\/code>; first argument is <code>1<\/code>)<\/td>\n<\/tr>\n<tr>\n<td><code>!^<\/code><\/td>\n<td>Expand first argument from most recent command<\/td>\n<\/tr>\n<tr>\n<td><code>!$<\/code><\/td>\n<td>Expand last token from most recent command<\/td>\n<\/tr>\n<tr>\n<td><code>!!:n-m<\/code><\/td>\n<td>Expand range of tokens from most recent command<\/td>\n<\/tr>\n<tr>\n<td><code>!!:n-$<\/code><\/td>\n<td>Expand <code>n<\/code>th token to last from most recent command<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><code>!!<\/code> can be replaced with any valid expansion i.e. <code>!cat<\/code>, <code>!-2<\/code>, <code>!42<\/code>, etc.<\/p>\n<h2 id=\"miscellaneous\">Miscellaneous<\/h2>\n<h3 id=\"numeric-calculations\">Numeric calculations<\/h3>\n<pre><code class=\"language-bash\">$((a + 200))      # Add 200 to $a\r\n<\/code><\/pre>\n<pre><code class=\"language-bash\">$(($RANDOM%200))  # Random number 0..199\r\n<\/code><\/pre>\n<h3 id=\"subshells\">Subshells<\/h3>\n<pre><code class=\"language-bash\">(cd somedir; echo \"I'm now in $PWD\")\r\npwd # still in first directory\r\n<\/code><\/pre>\n<h3 id=\"redirection\">Redirection<\/h3>\n<pre><code class=\"language-bash\">python hello.py &gt; output.txt   # stdout to (file)\r\npython hello.py &gt;&gt; output.txt  # stdout to (file), append\r\npython hello.py 2&gt; error.log   # stderr to (file)\r\npython hello.py 2&gt;&amp;1           # stderr to stdout\r\npython hello.py 2&gt;\/dev\/null    # stderr to (null)\r\npython hello.py &amp;&gt;\/dev\/null    # stdout and stderr to (null)\r\n<\/code><\/pre>\n<pre><code class=\"language-bash\">python hello.py &lt; foo.txt      # feed foo.txt to stdin for python\r\n<\/code><\/pre>\n<h3 id=\"inspecting-commands\">Inspecting commands<\/h3>\n<pre><code class=\"language-bash\">command -V cd\r\n#=&gt; \"cd is a function\/alias\/whatever\"\r\n<\/code><\/pre>\n<h3 id=\"trap-errors\">Trap errors<\/h3>\n<pre><code class=\"language-bash\">trap 'echo Error at about $LINENO' ERR\r\n<\/code><\/pre>\n<p>or<\/p>\n<pre><code class=\"language-bash\">traperr() {\r\n  echo \"ERROR: ${BASH_SOURCE[1]} at about ${BASH_LINENO[0]}\"\r\n}\r\n\r\nset -o errtrace\r\ntrap traperr ERR\r\n<\/code><\/pre>\n<h3 id=\"caseswitch\">Case\/switch<\/h3>\n<pre><code class=\"language-bash\">case \"$1\" in\r\n  start | up)\r\n    vagrant up\r\n    ;;\r\n\r\n  *)\r\n    echo \"Usage: $0 {start|stop|ssh}\"\r\n    ;;\r\nesac\r\n<\/code><\/pre>\n<h3 id=\"source-relative\">Source relative<\/h3>\n<pre><code class=\"language-bash\">source \"${0%\/*}\/..\/share\/foo.sh\"\r\n<\/code><\/pre>\n<h3 id=\"printf\">printf<\/h3>\n<pre><code class=\"language-bash\">printf \"Hello %s, I'm %s\" Sven Olga\r\n#=&gt; \"Hello Sven, I'm Olga\r\n\r\nprintf \"1 + 1 = %d\" 2\r\n#=&gt; \"1 + 1 = 2\"\r\n\r\nprintf \"This is how you print a float: %f\" 2\r\n#=&gt; \"This is how you print a float: 2.000000\"\r\n<\/code><\/pre>\n<h3 id=\"directory-of-script\">Directory of script<\/h3>\n<pre><code class=\"language-bash\">DIR=\"${0%\/*}\"\r\n<\/code><\/pre>\n<h3 id=\"getting-options\">Getting options<\/h3>\n<pre><code class=\"language-bash\">while [[ \"$1\" =~ ^- &amp;&amp; ! \"$1\" == \"--\" ]]; do case $1 in\r\n  -V | --version )\r\n    echo $version\r\n    exit\r\n    ;;\r\n  -s | --string )\r\n    shift; string=$1\r\n    ;;\r\n  -f | --flag )\r\n    flag=1\r\n    ;;\r\nesac; shift; done\r\nif [[ \"$1\" == '--' ]]; then shift; fi\r\n<\/code><\/pre>\n<h3 id=\"heredoc\">Heredoc<\/h3>\n<pre><code class=\"language-sh\">cat &lt;&lt;END\r\nhello world\r\nEND\r\n<\/code><\/pre>\n<h3 id=\"reading-input\">Reading input<\/h3>\n<pre><code class=\"language-bash\">echo -n \"Proceed? [y\/n]: \"\r\nread ans\r\necho $ans\r\n<\/code><\/pre>\n<pre><code class=\"language-bash\">read -n 1 ans    # Just one character\r\n<\/code><\/pre>\n<h3 id=\"special-variables\">Special variables<\/h3>\n<table>\n<thead>\n<tr>\n<th>Expression<\/th>\n<th>Description<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>$?<\/code><\/td>\n<td>Exit status of last task<\/td>\n<\/tr>\n<tr>\n<td><code>$!<\/code><\/td>\n<td>PID of last background task<\/td>\n<\/tr>\n<tr>\n<td><code>$$<\/code><\/td>\n<td>PID of shell<\/td>\n<\/tr>\n<tr>\n<td><code>$0<\/code><\/td>\n<td>Filename of the shell script<\/td>\n<\/tr>\n<tr>\n<td><code>$_<\/code><\/td>\n<td>Last argrument of the previous command<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>See <a href=\"http:\/\/wiki.bash-hackers.org\/syntax\/shellvars#special_parameters_and_shell_variables\">Special parameters<\/a>.<\/p>\n<h3 id=\"go-to-previous-directory\">Go to previous directory<\/h3>\n<pre><code class=\"language-bash\">pwd # \/home\/user\/foo\r\ncd bar\/\r\npwd # \/home\/user\/foo\/bar\r\ncd -\r\npwd # \/home\/user\/foo\r\n<\/code><\/pre>\n<h3 id=\"check-for-commands-result\">Check for command\u2019s result<\/h3>\n<pre><code class=\"language-bash\">if ping -c 1 google.com; then\r\n  echo \"It appears you have a working internet connection\"\r\nfi\r\n<\/code><\/pre>\n<h3 id=\"grep-check\">Grep check<\/h3>\n<pre><code class=\"language-bash\">if grep -q 'foo' ~\/.bash_history; then\r\n  echo \"You appear to have typed 'foo' in the past\"\r\nfi\r\n<\/code><\/pre>\n<h2 id=\"also-see\" class=\"-one-column\">Also see<\/h2>\n<ul>\n<li><a href=\"http:\/\/wiki.bash-hackers.org\/\">Bash-hackers wiki<\/a> <em>(bash-hackers.org)<\/em><\/li>\n<li><a href=\"http:\/\/wiki.bash-hackers.org\/syntax\/shellvars\">Shell vars<\/a> <em>(bash-hackers.org)<\/em><\/li>\n<li><a href=\"https:\/\/learnxinyminutes.com\/docs\/bash\/\">Learn bash in y minutes<\/a> <em>(learnxinyminutes.com)<\/em><\/li>\n<li><a href=\"http:\/\/mywiki.wooledge.org\/BashGuide\">Bash Guide<\/a> <em>(mywiki.wooledge.org)<\/em><\/li>\n<li><a href=\"https:\/\/www.shellcheck.net\/\">ShellCheck<\/a> <em>(shellcheck.net)<\/em><\/li>\n<\/ul>\n<div class=\"group\">\n<div class=\"related-posts-group\"><\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Original Website This is a quick reference to getting started with Bash scripting. Learn bash in y minutes (learnxinyminutes.com) Bash Guide (mywiki.wooledge.org) Example #!\/usr\/bin\/env bash NAME=&#8221;John&#8221; echo &#8220;Hello $NAME!&#8221; Variables NAME=&#8221;John&#8221; echo $NAME echo &#8220;$NAME&#8221; echo &#8220;${NAME}!&#8221; String quotes NAME=&#8221;John&#8221; echo &#8220;Hi $NAME&#8221; #=&gt; Hi John echo &#8216;Hi $NAME&#8217; #=&gt; Hi $NAME Shell execution echo [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[9,7,24],"tags":[],"class_list":["post-6085","post","type-post","status-publish","format-standard","hentry","category-bash","category-grundlagen","category-it-syntax"],"rttpg_featured_image_url":null,"rttpg_author":{"display_name":"speefak","author_link":"https:\/\/speefak.spdns.de\/oss_lifestyle\/author\/speefak_oss\/"},"rttpg_comment":0,"rttpg_category":"<a href=\"https:\/\/speefak.spdns.de\/oss_lifestyle\/category\/bash\/\" rel=\"category tag\">Bash<\/a> <a href=\"https:\/\/speefak.spdns.de\/oss_lifestyle\/category\/grundlagen\/\" rel=\"category tag\">Grundlagen<\/a> <a href=\"https:\/\/speefak.spdns.de\/oss_lifestyle\/category\/it-syntax\/\" rel=\"category tag\">IT Syntax<\/a>","rttpg_excerpt":"Original Website This is a quick reference to getting started with Bash scripting. Learn bash in y minutes (learnxinyminutes.com) Bash Guide (mywiki.wooledge.org) Example #!\/usr\/bin\/env bash NAME=\"John\" echo \"Hello $NAME!\" Variables NAME=\"John\" echo $NAME echo \"$NAME\" echo \"${NAME}!\" String quotes NAME=\"John\" echo \"Hi $NAME\" #=&gt; Hi John echo 'Hi $NAME' #=&gt; Hi $NAME Shell execution echo&hellip;","_links":{"self":[{"href":"https:\/\/speefak.spdns.de\/oss_lifestyle\/wp-json\/wp\/v2\/posts\/6085","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/speefak.spdns.de\/oss_lifestyle\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/speefak.spdns.de\/oss_lifestyle\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/speefak.spdns.de\/oss_lifestyle\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/speefak.spdns.de\/oss_lifestyle\/wp-json\/wp\/v2\/comments?post=6085"}],"version-history":[{"count":0,"href":"https:\/\/speefak.spdns.de\/oss_lifestyle\/wp-json\/wp\/v2\/posts\/6085\/revisions"}],"wp:attachment":[{"href":"https:\/\/speefak.spdns.de\/oss_lifestyle\/wp-json\/wp\/v2\/media?parent=6085"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/speefak.spdns.de\/oss_lifestyle\/wp-json\/wp\/v2\/categories?post=6085"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/speefak.spdns.de\/oss_lifestyle\/wp-json\/wp\/v2\/tags?post=6085"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}