25  25. Bash Scripts (and Using AI at the Command Line)

When you find yourself typing the same commands again and again, you can save them in a file and run the file instead. This page covers the basics of Bash scripts, and how to use AI safely when it writes commands and scripts for you.

25.1 What is a script?

A script is a text file that contains commands. When you run it, the shell executes the commands from top to bottom, exactly as if you had typed them one by one. Bash scripts usually have names ending in .sh.

Scripts let you repeat a task with one command (for example, setting up the folders for a new project, or backing up your files), share that task with others, and keep a record of exactly what you did.

25.2 Your first script

Open a new file in nano (any text editor works; see Writing to Files):

cd ~/Documents/bash-tutorial-files
nano hello.sh

Type these lines, then save (Ctrl+O, Enter) and exit (Ctrl+X):

#!/bin/bash
# hello.sh: my first script
echo "Hello from a script"
echo "You are in $(pwd)"

Run the script by handing it to Bash:

bash hello.sh

Output:

Hello from a script
You are in /Users/maria/Documents/bash-tutorial-files

The second line of the script is a comment: Bash ignores everything from a # to the end of the line. Comments are notes for people who read the script, such as what it does and how to use it. (Comments work inside script files. Typed at the zsh prompt on a Mac, they don’t, by default; see Getting Bash on Your Computer.)

25.3 The shebang line

The first line, #!/bin/bash, is called the shebang (“hash” + “bang”, the nicknames of # and !). It tells the operating system which program should run the script when you run the file directly, as in the next section. You will also see #!/usr/bin/env bash, which finds bash by searching your PATH.

On a Mac this means that the script runs in Bash, even though your Terminal uses zsh. (The Mac’s built-in Bash is an old version, 3.2, which is fine for simple scripts like these.)

25.4 Running a script like a command: chmod +x and ./

chmod +x hello.sh
./hello.sh
  • chmod +x (“change mode: add execute permission”) marks the file as a program that may be run. Without it, a Mac answers permission denied. (In Git Bash, a script that starts with #! usually runs even without chmod +x, but running it does no harm.)
  • ./hello.sh means “the file hello.sh in this folder.” If you type just hello.sh, the shell looks for it only in the folders on your PATH, and your current folder isn’t one of them, so you get command not found. This rule protects you from accidentally running a program just because it happens to sit in the current folder.

25.5 Variables and arguments

Scripts become really useful when they take input. Here is a script that sets up a starter folder for a new project:

#!/bin/bash
# new-project.sh: create a starter folder for a new project
# Usage: bash new-project.sh PROJECT-NAME

project="$1"
mkdir -p "$project/docs" "$project/src"
echo "# $project" > "$project/README.md"
echo "Created $project with docs/, src/ and README.md"
bash new-project.sh club-site

Output:

Created club-site with docs/, src/ and README.md
  • $1 is the first argument: the first word you typed after the script’s name (club-site). $2 is the second one, and so on. (That’s why $5 vanished on the quotes page.)
  • project="$1" stores the argument in a variable with a readable name.
  • The double quotes around "$project" keep a name that contains spaces in one piece.
  • echo "# $project" > "$project/README.md" writes a heading into a new README file. This # is inside quotes, so it’s ordinary text, not a comment.

Run it again with another name, such as bash new-project.sh budget-app, and you get a second, identical setup in seconds. That’s the point of a script.

25.6 Using AI safely at the command line

AI assistants are very good at writing commands and scripts, and they are sometimes confidently wrong. You are responsible for what runs on your computer. A good routine:

  1. Tell the AI your system and shell: “Mac, zsh in Terminal” or “Windows, Git Bash”.
  2. Ask it to explain each part of a command before you run it.
  3. Check where you are with pwd; most commands act on the current folder.
  4. Preview first. Run ls with the same wildcard before an rm or mv, and test new scripts on a copy of your files.
  5. Ask for comments in any script the AI writes, and read the script before you run it.

Never run commands like these unless you understand exactly what they will do:

Pattern Why it’s risky
rm -rf ... deletes files and whole folders permanently, without asking
sudo ... (Mac and Linux) runs the command with administrator rights, so it can change or break anything on the computer
curl … | bash downloads a script from the internet and runs it immediately, before anyone has read it
... > important-file replaces everything in the file

Some official installers do work this way: Homebrew’s installer for the Mac, for example, downloads a script with curl and runs it with Bash. That’s acceptable when you copied the command from the official website yourself, not when it comes from a forum post or an AI’s suggestion.

A good request looks like this:

I'm on a Mac using zsh. Write a Bash script that copies every .csv file in
the current folder into a new folder named backup. Add a comment to each
line, and tell me how to test it safely first.

25.7 Preview: Claude Code runs commands for you

As of Oct 6, 2026 · Official docs: Choose a permission mode · Advanced setup · Interactive mode

Claude Code doesn’t just suggest commands: it can run them itself, through its Bash tool. (On Windows, the Bash tool uses Git Bash, so it needs Git for Windows; without it, Claude Code runs commands through a PowerShell tool instead.) Whether it asks you first depends on its permission mode. In Manual mode, it asks before running shell commands. In auto mode, which recent versions normally start in, a separate safety check reviews most actions instead of you and blocks the risky ones. Either way, you can review the commands it ran (for example in its transcript view, opened with Ctrl+O), and they are the same kind of Bash commands you learned in this part of the book. Permission modes are covered in Permissions, Modes, and Safety.

Practice Questions

Easy

Question 1 · Short answer

What is a Bash script?

A text file containing shell commands. When you run it, Bash executes the commands from top to bottom, as if you had typed them yourself. Script names usually end in .sh.

Question 2 · Multiple choice

What does the first line #!/bin/bash of a script do?

  1. Nothing; it’s a comment
  2. It tells the operating system to run the script with Bash when you run the file directly
  3. It deletes the previous version of the script
  4. It makes the script executable

b. This is the shebang line. It looks like a comment (a), but on the first line #! has a special meaning: it names the program that should run the script. Making a file executable (d) is the job of chmod +x.

Question 3 · True or false

In a script, Bash runs the lines that start with # (after the first line) as commands.

False. Those lines are comments: Bash ignores everything from # to the end of the line. Only the special #! on the very first line has a meaning.

Question 4 · Short answer

What does chmod +x backup.sh do?

It gives backup.sh execute permission, so that it can be run directly as a command (./backup.sh).

Question 5 · Multiple choice

You run bash greet.sh Maria Lopez. Inside the script, what is the value of $2?

  1. greet.sh
  2. Maria
  3. Lopez
  4. Maria Lopez

c. $1 is the first argument after the script name (Maria), and $2 is the second (Lopez). To pass Maria Lopez as one argument, put it in quotes: bash greet.sh "Maria Lopez".

Medium

Question 6 · Write the command

Write the two commands that make report.sh executable and then run it from the current folder.

chmod +x report.sh
./report.sh

Question 7 · Short answer

hello.sh is in the current folder and is executable, but typing hello.sh gives command not found, while ./hello.sh works. Why?

A plain command name is looked up only in the folders listed in PATH, and the current folder is not on the PATH. ./hello.sh gives an explicit path (“hello.sh in this folder”), so no search is needed.

Question 8 · Predict the output

greet.sh contains:

#!/bin/bash
name="$1"
echo "Hello, $name. Welcome to the course."

What do these two commands print?

bash greet.sh Sam
bash greet.sh "Maria Lopez"
Hello, Sam. Welcome to the course.
Hello, Maria Lopez. Welcome to the course.

The quotes make Maria Lopez a single argument, so it all ends up in $1.

Question 9 · Find the bug

The script total.sh contains these lines:

#!/bin/bash
total = 5
echo "Total: $total"

Running it prints total.sh: line 2: total: command not found and then Total:. What’s wrong?

Variable assignments must not have spaces around =. With the spaces, Bash thinks total is a command to run. The line should be total=5; then the script prints Total: 5.

Question 10 · Write the script

Write a script backup-notes.sh that copies meeting-notes.txt to meeting-notes-backup.txt and then prints Backup saved. Include a shebang and a comment. Show how to run it.

#!/bin/bash
# backup-notes.sh: make a backup copy of the meeting notes
cp meeting-notes.txt meeting-notes-backup.txt
echo "Backup saved"

Run it with bash backup-notes.sh, or with chmod +x backup-notes.sh once and then ./backup-notes.sh. It must be run in the folder that contains meeting-notes.txt, because the script uses relative paths.

Question 11 · Matching

Match each command pattern with its risk.

Pattern Risk
1. rm -rf old-site A. downloads a script and runs it before anyone has read it
2. sudo ... B. replaces the contents of a file
3. curl -fsSL https://example.com/x.sh | bash C. permanently deletes a folder and everything in it, without asking
4. echo "" > notes.txt D. runs a command with administrator rights

1 → C, 2 → D, 3 → A, 4 → B.

Question 12 · Short answer

List four things you should tell or ask an AI assistant when you want it to write a command for you.

For example:

  1. Your operating system and shell (“Windows, Git Bash” or “Mac, zsh”).
  2. Exactly what you want to achieve, and which files or folders are involved.
  3. A request to explain each part of the command.
  4. A request for a safe way to preview or test it first (and comments, if it writes a script).

Hard

Question 13 · Scenario

Maria runs bash new-project.sh but forgets to type a project name. The script prints errors about /docs, /src, and /README.md. What happened, and how could the script protect itself?

Without an argument, $1 is empty, so project is empty and "$project/docs" becomes /docs: the script tries to create folders and a file at the very top of the file system (the root /). Luckily, normal users aren’t allowed to write there, so the commands fail with errors such as “Permission denied” or “Read-only file system”. With a command like rm -rf "$project"/*, an empty variable could be a disaster.

A script should check its input before doing anything, for example:

if [ -z "$1" ]; then
  echo "Usage: bash new-project.sh PROJECT-NAME"
  exit 1
fi

(-z tests whether the text is empty, and exit 1 stops the script.)

Question 14 · Scenario

While you’re trying to fix an error, a forum post suggests:

curl -fsSL https://fix-my-setup.example.net/repair.sh | bash

Explain what this would do and what you should do instead.

curl downloads the file repair.sh from that website, and | bash sends it straight into Bash, which runs it immediately with your permissions. Nobody (including you) reads the script first, and it could delete files, steal secrets such as API keys, or install malware. Instead: don’t run it. Find the official documentation for the tool you’re fixing, or download the script without running it (for example curl -fsSL URL -o repair.sh), read it, and ask an AI to explain it line by line, before deciding.

Question 15 · Scenario

An AI assistant says: “To fix this, run sudo rm -r /usr/local/lib/node_modules.” Sam is on Windows with Git Bash; Maria is on a Mac. What does the command do, and how should each of them respond?

sudo runs the command as an administrator (after asking for your password), and rm -r deletes the folder /usr/local/lib/node_modules and everything in it, permanently. Deleting system-wide folders as an administrator can break other programs.

  • Maria should not run it until she understands why that folder must go: ask the AI to explain the cause of the error and whether there is a safer fix that doesn’t need sudo, and check what the folder contains first.
  • Sam shouldn’t run it either: it’s a Mac/Linux command (Git Bash doesn’t include sudo, and /usr/local/lib/node_modules is a Mac/Linux path). The AI gave a command for the wrong system, a sign that he should tell it he uses Git Bash on Windows and ask again.

Question 16 · Long answer

Claude Code can run shell commands for you, and in auto mode a safety check approves most of them without asking. Why is it still important that you can read Bash commands?

A good answer mentions several of these points:

  • You remain responsible for what happens to your files and accounts; an automatic check reduces risk but can’t know everything you intend.
  • Reading the commands (for example in the transcript view) lets you notice mistakes early, such as the wrong folder, a dangerous wildcard, or a file being overwritten.
  • In Manual mode you must decide whether to approve each command, and that decision is only meaningful if you understand it.
  • Understanding the commands helps you learn, debug problems, and give the AI better instructions.

Question 17 · Ordering

Put these steps in order to create and run a new script:

  1. Run ./tidy.sh and check the output.
  2. Type the commands into the file, starting with #!/bin/bash.
  3. Run chmod +x tidy.sh.
  4. Open a new file with nano tidy.sh.
  5. Save with Ctrl+O, Enter, and exit with Ctrl+X.

d → b → e → c → a. Create the file, write the commands, save and exit, make it executable, then run it.

© 2025-2026 Y. Rosenthal. All rights reserved.