Simple Bash and Linux Commands Reference

This is my simple Linux commands and bash reference.


Table of contents

  1. Running Scripts
  2. Redirecting Input and Output
  3. Miscellaneous
  4. Variables
  5. Working with Arrays
  6. Script Arguments
  7. Conditional Statements
  8. CASE Instruction
  9. Loops
  10. Commands:
    1. find
    2. cat
    3. ls and dir
    4. wc
    5. echo and printf
    6. read
    7. od
  11. Examples

Running scripts


-x – run the script and show the commands being issued:

$ echo date > show_date.sh
$ chmod u+x show_date.sh
$ bash -x show_date.sh

+ date
Sun May  8 15:08:20 EDT 2016

& – executing commands to run in background.


Redirecting Input/Output

  • > – redirect standard output
  • >> – redirect standard output – append mode
  • 2> – redirect standard error output
  • < - redirect standard input
  • | - pipe one command's output as input to another command
  • << - used to provide input for a command - the following will produce file myfile.txt with three lines:
    $ cat > myfile.txt << END
    > a
    > b
    > c
    > END
    $ cat myfile.txt 
    a
    b
    c

Miscellaneous


~ - shortcut to home directory:

$ pwd
/home/oracle/Desktop/scripts
$ cd ~
$ pwd
/home/oracle

`...` (backquote) - used to replace a command with its output:

$ `echo pw``echo d`
/home/oracle/Desktop/scripts

echo prints its arguments, which results in pwd. Since it is the first word, it is treated as a command to be executed.


$ touch a
$ touch "a b.txt"
$ find . -name "*.txt"
./a b.txt

$ rm `find . -name "*.txt"`
rm: cannot remove `b.txt': No such file or directory
$ ls -1
a b.txt

One needs to be careful with names that have spaces: in the above example rm removed the a file instead of a b.txt.


Quotes and apostrophes - prevent interpreter from substituting characters like *

Apostrophes also make interpreter treat strings of $var type as a regular string, not a variable:

$ VAR=value
$ echo $VAR
value
$ echo $VAR *
value myfile.txt
$ echo "$VAR *"
value *
$ echo '$VAR *'
$VAR *

Calling subshell = using parentheses, a set of instruction can be run in a subshell, and their output can be treated as a whole for next command:

$ (for i in *.txt; do cat $i; done) | sort

Variables

Assigning a value:

variable_name=value

$ - use dollar sign to access the value:

echo $variable_name

# - use to get the length of a variable:

$ echo ${#variable_name}
5

Calculation of arithmetic expressions - two possibilities:

  • $[ ... ] - built-in bash functionality
  • expr command

Dollar signs are not required in front of variables inside $[ ... ] and * is not considered a pattern.

Examples:

$ var=$[2 + 2]
$ echo $var
4
$ var=`expr $var \* 2`
$ echo $var
8
$ var=`expr $var * 2`
expr: syntax error
$ var=`expr var \* 2`
expr: non-numeric argument

expr requires dollar signs and escaping * with \


environment variable - to make a variable an environmental variable (and available to child processes), it must be exported:

$ export MYVAR=abc

# or

$ MYVAR=abc
$ export MYVAR

Checking length of a variable: ${#variable}


Working with Arrays

Using arrays:

array=(Cake Cookie "Ice Cream")
array[3]=Fruit

echo $array        # -> Cake - $array points to the first element
echo ${array[1]}   # -> Cookie

echo ${array[*]}   # -> Cake Cookie Ice Cream Fruit
echo ${array[@]}   # -> Cake Cookie Ice Cream Fruit
echo ${!array[*]}  # -> indexes: 0 1 2 3
echo ${#array[*]}  # -> 4 - the number of elements
echo ${#array[3]}  # -> 5 - the length of fourth element

# extract two elements, starting at index 1
echo ${array[@]:1:2} # -> Cookie Ice Cream

# extract part of a given element, starting at index 0
echo ${array[0]:0:3} # -> Cake

The difference between [*] and [@]:

array2=(${array[*]})   # returns elements split by spaces
array3=("${array[*]}") # returns a single element
array4=("${array[@]}") # returns elements as in the orignal array

echo \${array2[*]}
for i in ${!array2[*]}; do
  echo ${array2[$i]}
done

echo \"\${array3[*]}\"
for i in ${!array3[*]}; do
  echo ${array3[$i]}
done

echo \"\${array4[@]}\"
for i in ${!array4[*]}; do
  echo ${array4[$i]}
done

Output:

${array2[*]}
Cake
Cookie
Ice
Cream
Fruit

"${array3[*]}"
Cake Cookie Ice Cream Fruit

"${array4[@]}"
Cake
Cookie
Ice Cream
Fruit

Script Arguments

Script arguments can be accessed using:

  • $1, $2, ..., $9 - for the first nine arguments
  • (for example) ${13} - for other arguments

Other values:

  • $0 - name of the script
  • $# - number of arguments
  • $@ - all script's arguments
  • $* - all script's arguments
  • Difference between the last two:

    ./foo.sh "a a" "b b" "c c"

    asterisk "$*": "a a b b c c"
    at-sign "$@": "a a" "b b" "c c"

    Without the quotes, they're the same:

    asterisk $*: "a" "a" "b" "b" "c" "c"
    at-sign $@ "a" "a" "b" "b" "c" "c"

    shift [n] command can be used to shift arguments to the right, losing the first argument $1, and moving argument $2 to its position, moving $3 to $2 and so on - n, by default 1, specifies number of arguments to be shifted. $# and $@ are updated after a shift.


    Conditional Statements

    Conditional statements - if..then..elif..else..fi - syntax:

    if condition1; then
      ...
    elif conditon2; then
      ...
    else
      ...
    fi

    test - command which evaluates its arguments - if they are true, it returns with code 0, and 1 otherwise.

    $ if test 1 == 1; then echo 1 == 1; else echo 1 != 1; fi
    1 == 1

    Instead of using test, square brackets can be used:

    $ if [ 1 == 1 ] ; then echo 1 == 1; else echo 1 != 1; fi
    1 == 1

    AND and OR - && and ||

    test command flags - files:

    • -c text file exists
    • -d directory exists
    • -e file exists
    • -f file exists and is a regular file
    • -h file exists and is a symbolic link
    • -r file can be read
    • -w file can be written to
    • -x file can be run
    • file1 -nt file2 file1 is newer than file2
    • file1 -ot file2 file1 is older than file2

    Arithmetic operations:

    • -eq - equal to
    • -ne - not equal to
    • -lt - lower than
    • -le - lower equal
    • -gt - greater than
    • -ge - greater equal

    String operations:

    • = - equal
    • != - not equal
    • < - first string is "smaller"
    • > - first string is "larger"
    • -n - expression has length > 0
    • -z - expression has length = 0

    CASE instruction

    Syntax of case instruction:

    case variable in
      pattern1) instruction1 ;;
      pattern2) instruction2 ;;
      * instruction_else ;;
    esac

    * - can be used to match any (also empty) character string (for example c*t matches cat, caat, cut, and so on),
    ? - can be used to match a single character.

    Example:

    case $1 in
      pattern1) echo ;;
      pattern2) instruction2 ;;
      * instruction_else ;;
    esac

    Loops

    while .. do loop syntax:

    while condition; do
      instruction;
    done

    Example:

    $ i=4
    $ while [ $i -gt 0 ] ; do
    >  echo $i;
    >  i=$[i - 1];
    >done
    
    4
    3
    2
    1

    Or, in one line: while [ $i -gt 0 ] ; do echo $i; i=$[i - 1]; done

    for loop:

    for var in list; do
      instruction;
    done

    Or, to iterate over program's arguments ($1, $2 and so on):

    for var; do
      instruction;
    done

    Commands

    find

    find - has an -exec option which can perform an action on every found file:

    $ find . -name "*.txt" -exec rm "{}" \;

    {} is replaced by the name of the found file
    \; - one invocation per found file
    + - collects filenames up to ARG_MAX and then executes the command - less invocations than using \;

    Example:

    find . -name "*.txt" -exec rm "{}" +

    There's also -execdir option - difference is that -exec executes the command from the starting directory, whereas the -execdir from the directory where the file has been found:

    $ touch a.txt
    $ mkdir subdir
    $ touch subdir/b.txt
    
    $ find . -name "*.txt" -exec pwd \;
    /home/oracle/Desktop/scripts/rm_test
    /home/oracle/Desktop/scripts/rm_test
    
    $ find . -name "*.txt" -execdir pwd \;
    /home/oracle/Desktop/scripts/rm_test/subdir
    /home/oracle/Desktop/scripts/rm_test

    cat

    cat - prints its input:

    cat > test.txt
    line1
    line2
    ^D
    cat test.txt
    line1
    line2 <-- no new line here

    ls and dir

    ls and dir - dir's default output format does not depend on the type of the output device type - it's always vertically sorted columns, whereas in case of ls, it outputs one file per line if the output device is not the terminal.

    ls -1 - one file per line (minus one, not minus lower-case L)


    wc

    wc -l - count lines
    wc -c - count bytes - also counts newline
    wc -m - count characters - also counts newline


    echo and printf

    echo outputs carrige return, printf does not:

    $ echo t > wc_test
    $ printf t > wc_test2
    
    $ wc -c wc_test
    2 wc_test
    
    $ wc -c wc_test2
    1 wc_test2
    
    $ wc -m wc_test
    2 wc_test
    
    $ wc -m wc_test2
    1 wc_test2

    read

    read command - reads one line from standard input and splits it into words, putting the tokens into variables passed to read - the remaining words are stored in the last variable:

    $ read x y
    one two three
    $ echo x = $x
    x = one
    $ echo y = $y
    y = two three

    od

    od command can be used to investigate the characters:

    $ echo k | od -t c
    0000000   k  \n
    0000002
    $ od -t c wc_test
    0000000   t  \n
    0000002
    $ od -t c wc_test2
    0000000   t
    0000001

    od - shows representation of characters:

    • -t a - named character display format
    • -t c - ASCII character display format
    $ od -t a wc_test
    0000000   t  nl
    0000002

    Examples

    Removing a directory if it exists

    1. Check if a directory exists.
    2. Remove the directory and all its contents.
    REPO_DIR=/my/dir
    
    if [ -d "$REPO_DIR" ]; then
      echo "Removing $REPO_DIR"
      rm -rf "$REPO_DIR"
    fi

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *