Arguments: $1, $2, $@
A script can take arguments, the words you type after its name. Inside the script, $1 is the first, $2 the second, and so on. $0 is the script's own name, $# how many arguments there were, and $@ all of them:
cat <<'EOF' > greet.sh
#!/bin/bash
echo "Running $0"
echo "Hello, $1 and $2"
echo "You gave $# arguments: $@"
EOF
chmod +x greet.sh
./greet.sh Ada BoIn the terminal
student@vulntech:~$ cat <<'EOF' > greet.sh > #!/bin/bash > echo "Running $0" > echo "Hello, $1 and $2" > echo "You gave $# arguments: $@" > EOF student@vulntech:~$ chmod +x greet.sh student@vulntech:~$ ./greet.sh Ada Bo Running ./greet.sh Hello, Ada and Bo You gave 2 arguments: Ada Bo
Run it with different words and the output changes. This is how real commands take their arguments: when you type cp a b, cp sees $1 as a and $2 as b.
Asking the user: read
read pauses the script and reads a line the user types into a variable. -p shows a prompt first:
cat <<'EOF' > ask.sh
#!/bin/bash
read -p "What is your name? " who
echo "Welcome aboard, $who!"
EOF
chmod +x ask.sh
echo Grace | ./ask.shIn the terminal (the name is piped in, as if typed)
student@vulntech:~$ cat <<'EOF' > ask.sh > #!/bin/bash > read -p "What is your name? " who > echo "Welcome aboard, $who!" > EOF student@vulntech:~$ chmod +x ask.sh student@vulntech:~$ echo Grace | ./ask.sh Welcome aboard, Grace!
Exit codes: did the script succeed?
Every command ends with an exit code: 0 for success, anything from 1 to 255 for a problem. Your script sets its own with exit. Other scripts (and &&, ||) rely on it:
cat <<'EOF' > check.sh
#!/bin/bash
if [ -f "$1" ]; then
echo "$1 exists"
exit 0
else
echo "$1 is missing"
exit 1
fi
EOF
chmod +x check.sh
./check.sh /etc/hostname
echo $?
./check.sh /etc/nope
echo $?In the terminal
student@vulntech:~$ cat <<'EOF' > check.sh > #!/bin/bash > if [ -f "$1" ]; then > echo "$1 exists" > exit 0 > else > echo "$1 is missing" > exit 1 > fi > EOF student@vulntech:~$ chmod +x check.sh student@vulntech:~$ ./check.sh /etc/hostname /etc/hostname exists student@vulntech:~$ echo $? 0 student@vulntech:~$ ./check.sh /etc/nope /etc/nope is missing student@vulntech:~$ echo $? 1
Tip:
exiton its own passes on the exit code of the last command that ran. A script with noexitdoes the same.
Common mistake:
$1is empty if the user gave no arguments. Check withif [ -z "$1" ]; then echo "Usage: $0 FILE"; exit 1; fiat the top of a script.
Remember:
$1,$2are the arguments,$@all of them,$#the count.readasks the user.exit 0= success, non-zero = failure.