Unix Shell Scripts   «Prev  Next»
Lesson 3 Defining a script file
Objective Explain what makes a file a shell script in Unix

Defining a Unix Shell Script File

A shell script is a plain text file that contains commands you could type at a shell prompt, written in the syntax of a specific shell. What turns that text file into an executable “program” is not the filename or extension—it is how the file identifies its interpreter, how it is executed, and whether its contents are valid for that interpreter.

For a file to function as a shell script, it must meet these requirements:
  1. Interpreter line (shebang): the first line identifies which shell (or interpreter) should execute the file.
  2. Executable permission (when run directly): the file permissions must allow execution when you run it as ./scriptname.
  3. Valid commands: the file must contain commands and syntax that are valid for the chosen shell.

In this lesson you will also learn why script portability matters, how line endings can break scripts, and how filename patterns (wildcards) commonly appear inside scripts when working with groups of files.

Interpreter Selection with the Shebang Line

The first line of a script typically begins with #! and is called the shebang line. It tells the operating system which interpreter should execute the file when you run it directly.

A portable POSIX-style script often uses:
#!/bin/sh

On many modern Linux systems, /bin/sh may be linked to a smaller shell (such as dash) rather than bash. That is good for speed, but it means bash-only features (like arrays or [[ ... ]]) may fail if your script claims to be sh.

If your script requires bash features, you should explicitly target bash. A common modern approach is:
#!/usr/bin/env bash

This allows the system to locate bash using the user’s environment (helpful on systems where bash is not located at /bin/bash).

Historically, other shells could also be specified (for example, C shell):
#!/bin/csh

The key point: the interpreter line defines which shell parses your script. You can be logged into one shell interactively and still run scripts written for another shell, because the shebang controls script execution.

Permissions and How Scripts Are Invoked

On Unix systems, scripts are governed by file permissions. To run a script directly (for example ./welcome), it must have the execute bit set:

$ chmod +x welcome

If a script is not executable, you can still run it by passing it to a shell explicitly:

$ sh welcome
$ bash welcome

In those cases, the execute bit is not required because you are running the interpreter and giving it a file as input.

Permission problems are one of the most common “first script” issues. If you see an error such as “Permission denied,” check:
  • you are invoking the file correctly (./script vs script)
  • the script has execute permission (ls -l)
  • the filesystem is not mounted with noexec (common on some shared or removable mounts)

Valid Commands and Script Correctness

A shell script must contain commands that are valid for the interpreter declared on the first line. For example, if your script begins with #!/bin/sh, you should use portable POSIX syntax. If your script begins with #!/usr/bin/env bash, you may use bash-specific features.

Two additional modern “gotchas” are worth knowing early:
  • Line endings: scripts edited on Windows may contain CRLF line endings, which can trigger errors such as /bin/sh^M: bad interpreter. Use a Unix-aware editor, or convert the file to Unix line endings.
  • Hidden characters and encoding: scripts should be plain text (UTF-8 is fine), but avoid smart quotes and hidden formatting characters that some editors insert.

The following diagram summarizes the three required components of a valid script file.

#!/usr/bin/env bash

set -euo pipefail

# ========================
# Sample Bash script
# Displays a support message
# ========================

echo "Contact your agent about /etc/smb.conf"
A valid script file identifies its interpreter on the first line, has execute permission when run directly, and contains valid commands for the selected shell.

Putting It Together: A Valid Script Example

#!/bin/sh

#========================
# This sample script contains only
# a few commands.
#========================

echo -n Contact your agent about.
echo /etc/smb.conf
A valid script is marked with correct file permissions and includes valid commands.

  1. The file permissions are set to include Execute (x)
  2. The first line of the script includes the path of the script interpreter
  3. The script contains valid commands

Practical scripting note: As you begin writing more scripts, you will frequently use variables, tests, and file operations. A good habit is to quote variables unless you explicitly want word-splitting:
$ echo "$HOME"
This single habit prevents a large class of bugs when filenames contain spaces or special characters.

Shell Script File Extensions

Unlike some operating systems, Unix does not require file extensions to identify file type. Shell scripts may have no extension at all. You may sometimes see .sh as a naming convention to help humans recognize a shell script, but the extension is not what makes the file executable. A file can be named anything and still be a valid shell script if it meets the requirements in this lesson.

Wildcards in Scripts

Shell scripts often operate on groups of files rather than a single filename. To do that, scripts rely on wildcards (also called filename patterns or globbing). Understanding wildcard behavior matters because scripts can unintentionally match more files than intended if patterns are too broad.

Wild card / Shorthand Meaning Examples
* Matches any string or group of characters.
$ ls *will show all files
$ ls a*will show all files whose first name is starting with letter 'a'
$ ls *.cwill show all files having extension .c
$ ls ut*.cwill show all files having extension .c but file name must begin with 'ut'.
? Matches any single character.
$ ls ?will show all files whose names are 1 character long
$ ls fo?will show all files whose names are 3 character long and file name begin with fo
[...] Matches any one of the enclosed characters
$ ls [abc]*will show all files beginning with letters a,b,c
Wildcards (globbing) let scripts match sets of filenames using shorthand patterns. Note: [..-..] denotes a range. A pair of characters separated by a minus sign matches any character in that range.
Example:
$ ls /bin/[a-c]*
This lists files in /bin that begin with a, b, or c.

Example output may include:
/bin/arch /bin/awk /bin/bsh /bin/chmod /bin/cp
/bin/ash /bin/basename /bin/cat /bin/chown /bin/cpio
/bin/ash.static /bin/bash /bin/chgrp /bin/consolechars /bin/csh

To match characters not in a range, many shells support negation inside brackets:
$ ls /bin/[!a-o]*
$ ls /bin/[^a-o]*

Safety tip: When using wildcards in scripts—especially with destructive commands like rm—test your pattern first with a harmless command like ls or printf '%s\n' to confirm what will match.

Scripts are typically created in a text editor. The next lesson introduces the vi editor so you can create and edit scripts efficiently in a Unix environment.

Defining Script File - Quiz

Click the Quiz link below to test yourself on what you have learned about what makes a file a valid shell script.
Defining Script File - Quiz

[1]File permission: An access right assigned to a file to determine which user can read, write, or execute a UNIX file.
[2]File extension: The last part of a filename, usually separated by a period (such as .tif or .doc), which indicates the format or function of the file.
SEMrush Software 3 SEMrush Banner 3