Power user
Your first shell script
Write a shell script from nothing: what a script is, the first line, making it run, running it, a variable, a loop, and what to do when it goes wrong.
On this page
What it is
A A text file of commands that runs them in order, so a task you repeat becomes one command. is a text file with One instruction you type in a terminal, such as ls (list the files here). Return runs it. in it, one under the other. You write the commands once. From then on, one short word runs all of them, in order, the same way every time.
A shell script is written in the language you already type in the terminal. Everything What a terminal is and zsh basics taught works inside one: ls, cd, echo, paths, quotes. This page writes the scripts in bash, the shell language of most scripts you will find on the web; it reads almost the same as zsh.
You need nothing you do not already have: Text Editor to write the file, and a terminal to run it.
Why it is worth it
Anything you type more than twice is worth a script. A script does not forget a step, does not mistype a folder name at the end of a long day, and does the job the same way next month. It is also easy to share: send the file, and someone else does exactly what you did.
WolOS treats a script with care. It runs as you, with your permissions, never as the system's own account. Before you run a script you can ask WolOS to read it and point out mistakes, without running a single line.
How
1. Make a file
Open Text Editor (press Super+Space and type "text"), and type these four lines exactly:
#!/usr/bin/env bash
# My first script: says hello.
echo "Hello!"
echo "Today is $(date +%A)."Save it in your home folder with the name hello. A script needs no ending on its name; the first line says what it is.
What each line does:
| Line | Means |
|---|---|
#!/usr/bin/env bash | The first line, called the The first line of a script, starting with #! (hash and exclamation mark). It names the program that reads the rest of the file.. It says: "read this file with bash". It must be the very first line, with nothing before #!. |
# My first script: says hello. | A comment. Every line that starts with # is for people; the computer skips it. Say what the script does, so you still know in a year. |
echo "Hello!" | Prints Hello! in the terminal. |
echo "Today is $(date +%A)." | $(…) runs a command and puts its answer into the text. date +%A answers with the name of the day. |
2. Make it run
Open a terminal (Super+Return). Your home folder is where the terminal starts, so the file is right there. Type:
chmod +x helloand press Return. chmod +x gives the file permission to run, the way a program has it. It prints nothing; silence means it worked. You do this once per script.
Why this step: a text file you download or write is never allowed to run on its own. You decide which files are programs. That keeps a file that only looks like a document from starting anything.
3. Run it
./helloYou see:
Hello!
Today is Wednesday../ means "in the folder I am in". The terminal runs only programs it knows by name, so a script of your own needs that short The address of a file: the folders you go through to reach it, separated by /. For example /home/alice/Documents/notes.txt. in front of it.
You can also run it with WolOS's own command:
wol script run helloThat works even before chmod +x. And to have the script read for mistakes without running any of it:
wol script check helloWhen everything is right you see one line, hello: bash script, parses. Parses means every line made sense. With the Developer module installed, the line also says that a style checker found nothing to improve.
4. A variable
A A name that holds a value, such as a word or a number, so you can use it again further down. is a name that holds a value. Make a new file, greet:
#!/usr/bin/env bash
# Says hello to someone.
name="Alice"
echo "Hello, $name!"name="Alice" puts the word Alice in the variable name. $name takes it out again. Run chmod +x greet, then ./greet, and you see Hello, Alice!.
A script becomes more useful when you tell it the value when you run it. Change the third line to:
name="$1"$1 is the first Extra words after a command that tell it what to work on, such as Documents in ls Documents. you give the script. Now:
./greet Alice
./greet "Alice Liddell"print Hello, Alice! and Hello, Alice Liddell!. The quote marks around Alice Liddell make the two words one argument.
5. A loop
A A part of a script that runs again for each item in a list, such as each photo in a folder. runs the same lines once for each item in a list. This script lists the photos in a folder of Pictures and counts them. Save it as photos:
#!/usr/bin/env bash
# Lists the photos in a folder of Pictures and counts them.
# How: ./photos Holiday
folder="$HOME/Pictures/$1"
if [ ! -d "$folder" ]; then
echo "There is no folder called $1 in Pictures."
exit 1
fi
count=0
for photo in "$folder"/*; do
echo "Found: $(basename "$photo")"
count=$((count + 1))
done
echo "$count photos in $1."Run chmod +x photos, then ./photos Holiday:
Found: Summer Trip.jpg
Found: beach.jpg
Found: cake.JPG
3 photos in Holiday.Read it from the top:
| Lines | Mean |
|---|---|
folder="$HOME/Pictures/$1" | $HOME is your home folder. With Holiday, the variable holds the path of Pictures/Holiday. |
if [ ! -d "$folder" ]; then … fi | If there is no such folder (! is not, -d is is a folder), say so and stop. fi closes the if. |
exit 1 | Stops the script and reports that it failed (below). |
count=0 | A variable to count with. |
for photo in "$folder"/*; do … done | The loop. * stands for every file in the folder; for each one, photo holds its path and the lines between do and done run. |
basename "$photo" | The name of the file without the folders in front of it. |
count=$((count + 1)) | $((…)) does arithmetic: one more than before. |
The name Summer Trip.jpg has a space and still comes through whole, because every variable is in double quotes.
6. Did it work? The exit status
Every command ends with an A number every command leaves behind when it ends: 0 means it worked, any other number means something went wrong.: a number, 0 when it worked, anything else when it did not. The prompt arrow turns red after a command that did not end with 0, and echo $? prints the number of the last one:
./photos Holidya
There is no folder called Holidya in Pictures.
echo $?
1exit 1 in the script is how photos says "this did not work". Use 1 for a failure and let the script end normally when everything went well; the end of a script is a 0.
By itself, bash carries on after a command fails. To make a script stop at the first command that fails, put this line right under the first one:
set -eA worked example
Alice wants a copy of her Documents folder every Friday, kept in a folder named after the day. She writes backup:
#!/usr/bin/env bash
# Copies Documents into a folder in Backups named after today.
# How: ./backup
set -e
today=$(date +%Y-%m-%d)
mkdir -p "$HOME/Backups/$today"
cp -r "$HOME/Documents" "$HOME/Backups/$today/"
echo "Saved a copy in Backups/$today."date +%Y-%m-%d answers with the date as 2026-11-04. mkdir -p makes the folder, and the folders above it if they are missing. cp -r copies a folder with everything in it. set -e makes sure the last line is printed only when the copy really happened.
She runs wol script check backup (it says backup: bash script, parses), then chmod +x backup and ./backup, and sees Saved a copy in Backups/2026-11-04. In Files, Backups now holds a folder for today with Documents inside. Every Friday she presses Super+Return, types ./backup and presses Return.
If something goes wrong
The terminal tells you in one line what it did not like. The line often starts with the script's name and the number of the line in the file.
| What you see | What it means and what to do |
|---|---|
zsh: permission denied: ./hello | The file may not run yet. Type chmod +x hello once, then run it again. |
zsh: command not found: hello | You left out ./ in front of the name. Type ./hello. |
zsh: no such file or directory: ./hello | No file has that name in the folder you are in. ls shows what is there; capitals matter. |
line 2: name: command not found | Spaces around =. Write name="Alice", with no spaces. |
line 3: ech: command not found | A mistyped command on that line. Fix the spelling, save, and run it again. Without set -e the script carries on after this. |
unexpected EOF while looking for matching and a quote mark | A quote mark is opened and never closed. wol script check names the line; count the quote marks on it. |
Hello, ! | The script needs an argument and got none. Add it after the name: ./greet Alice. |
Found: * and 1 photos | The folder is empty or its name is wrong, so * matched nothing. The check at the top of photos catches a wrong name. |
/usr/bin/env: 'bash\r': No such file or directory | The file was saved on Windows, with line endings bash does not read. Open it in Text Editor and save it again. |
| The script runs for ever | Press Ctrl+C to stop it, then look at the loop: something in it never ends. |
The next step is Your first Ruby script: the same ladder, with a language that keeps a name with a space in it whole without any quote marks. Scripts and shells shows how to run a script on another computer.
Related
- Your first Ruby scriptWrite a script in rsh, Ruby with terminal commands in it: a file ending in .rsh, Ruby and commands on the same page, why each value stays one argument, catching a command that failed, and running it with ./ and with wol script.
- Scripts and shellsRun sh, bash and Ruby scripts with wol script: checked before they run, as you, every change asked on screen and every run recorded. And choose the shell new terminal windows open in, PowerShell included.
- What a terminal isThe window where you type instead of click: what the prompt, a command, an argument and a path are, how to copy and paste, Tab, Ctrl+C, and your first five commands.
- Scripts that change settingsWrite a small Ruby script in a text editor, check it with wol script check, run it with wol script run, and see what WolOS asks before a script changes anything.
- zsh basicsThe shell in every WolOS terminal: history, Tab, suggestions, the colours of a command line, wildcards, pipes, saving output to a file, and your own settings.