m-chrzan.xyz
aboutsummaryrefslogtreecommitdiff
path: root/bash.md
blob: 432bc5ea46723b811a8250430131804823412021 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# Bash scripting

## String manipulation

Remove shortest from end

    ${VAR%substr}
    # e.g.
    ${FILEPATH%.*}.out   # change extension from whatever to .out

Remove longest from start

    ${VAR##substr}
    # e.g.
    ${FILEPATH##*/}      # get only file name portion

%% - longest from end, # - shortest from start

## Control flow

Loop over files

    for file in glob/*; do something $file; done

Loop over integers

    for i in `seq 10`; do echo $i; done

## Conditionals

* `-z`: is empty string
* `-n`: non-empty string
* `-f`: is regular file
* `$A == $B`: string equality, accepts globs
* `$A != $B`: string inequality

## Heredocs

    cat << EOF > file
    bla bla
    EOF

Ignoring the initial indent:

    ...
        cat <<- EOF > file
        bla bla
        EOF
    ...

Don't interpolate variables:

    cat << 'EOF' > file
    bla bla
    EOF

## Arrays

Declaring indexed arrays:

    declare -a name

Associative arrays:

    declare -A name

Assignment:

    # Indexed
    array=(foo bar "baz bom"...)
    # Associative
    array=([bla]=foo [ble]=bar...)

All values:

    ${array[*]} # one word, elements separated with first character of $IFS
    ${array[@]} # separate words when double quoted

All keys:

    ${!array[*]}
    ${!array[@]}

So looping:

    # Over values
    for x in "${array[@]}"; do ...
    # Over keys (0-based indices for indexed)
    for x in "${!array[@]}"; do ...


Array size:

    ${#array[@]}

Slice:

    # n elements starting at index i
    ${array[@]:i:n}

## Commandline arguments

* `$#`: number of arguments.

## Getopts example

    while getopts 'a:b:c' flag; do
      case "${flag}" in
        a) do_something $OPTARG ;;
        b) b_option=$OPTARG ;;
        c) c_flag=1 ;;
        *) error "Unexpected option ${flag}" ;;
      esac
    done

### With positional arguments

Positional arguments will have to be supplied after flag options (`command
[options] <args>`):

    shift $((OPTIND-1))


## Shell optional behavior/settings/options (`shopt` builtin)

    # Enable
    shopt -s <option>
    # Disable
    shopt -u <option>

* `nocaseglob`: glob matching is case insensitive