Defining a function
A function is a named block of commands you can call again and again. Inside it, $1, $2 and $@ are the function's own arguments, just like in a script:
greet() {
echo "Hello, $1!"
}
greet Ada
greet LinusIn the terminal
student@vulntech:~$ greet() { > echo "Hello, $1!" > } student@vulntech:~$ greet Ada Hello, Ada! student@vulntech:~$ greet Linus Hello, Linus!
Return values
A function reports success or failure with return and an exit code, which you test with if exactly as for any command:
is_even() {
if [ $(( $1 % 2 )) -eq 0 ]; then return 0; else return 1; fi
}
if is_even 10; then echo "10 is even"; fi
if is_even 7; then echo yes; else echo "7 is odd"; fiIn the terminal
student@vulntech:~$ is_even() { > if [ $(( $1 % 2 )) -eq 0 ]; then return 0; else return 1; fi > } student@vulntech:~$ if is_even 10; then echo "10 is even"; fi 10 is even student@vulntech:~$ if is_even 7; then echo yes; else echo "7 is odd"; fi 7 is odd
To hand back a piece of text instead, echo it and catch it with $( ):
double() {
echo $(( $1 * 2 ))
}
result=$(double 21)
echo "double 21 is $result"In the terminal
student@vulntech:~$ double() { > echo $(( $1 * 2 )) > } student@vulntech:~$ result=$(double 21) student@vulntech:~$ echo "double 21 is $result" double 21 is 42
local variables
Mark a function's own variables local so they don't clobber ones outside it. Without local, every variable is shared across the whole script, which causes surprising bugs:
count=99
add() {
local count
count=$(( $1 + $2 ))
echo "inside: $count"
}
add 2 3
echo "outside: $count"In the terminal
student@vulntech:~$ count=99 student@vulntech:~$ add() { > local count > count=$(( $1 + $2 )) > echo "inside: $count" > } student@vulntech:~$ add 2 3 inside: 5 student@vulntech:~$ echo "outside: $count" outside: 99
A small tool, put together
Here's everything so far in one script: a function, a loop, an if and arguments. It counts how many of the files you name actually exist:
cat <<'EOF' > count-files.sh
#!/bin/bash
exists() { [ -e "$1" ]; }
found=0
for path in "$@"; do
if exists "$path"; then
echo "found: $path"
found=$(( found + 1 ))
else
echo "missing: $path"
fi
done
echo "$found of $# exist"
EOF
chmod +x count-files.sh
./count-files.sh /etc/hostname /etc/nope /bin/bashIn the terminal
student@vulntech:~$ cat <<'EOF' > count-files.sh > #!/bin/bash > exists() { [ -e "$1" ]; } > found=0 > for path in "$@"; do > if exists "$path"; then > echo "found: $path" > found=$(( found + 1 )) > else > echo "missing: $path" > fi > done > echo "$found of $# exist" > EOF student@vulntech:~$ chmod +x count-files.sh student@vulntech:~$ ./count-files.sh /etc/hostname /etc/nope /bin/bash found: /etc/hostname missing: /etc/nope found: /bin/bash 2 of 3 exist
Remember:
name() { ...; }defines a function; call it like a command.$1is its first argument,return Nits exit code, andlocalkeeps a variable to itself.