How to Run a .sh File in Linux: Every Method Explained

You downloaded a script, or wrote one yourself, and now you have a file ending in `.sh` sitting in a folder. You type its name, hit Enter, and Linux throws back `Permission denied` or `command not found`. Frustrating — but those errors are actually Linux doing its job. Learning how to run a .sh file in Linux takes about five minutes, and once you understand *why* each method works, you will never be stuck on those errors again.

A `.sh` file is a shell script: a plain text file containing a list of commands that the shell runs top to bottom, exactly as if you typed them yourself. There are three clean ways to execute one, and this guide covers all of them with copy-paste code, plus every common error and its fix.

Key Takeaways
• A .sh file is just a text file of shell commands — it is not “runnable” until you say so.
Fastest one-off: `bash script.sh` (no permission changes needed at all).
For scripts you run often: `chmod +x script.sh` once, then `./script.sh` forever after.
`Permission denied` means the execute bit is not set — run `chmod +x script.sh` or use `bash script.sh`.
`./` is required because the current directory is not in your `PATH` (a deliberate security choice).
• The shebang line (`#!/bin/bash`) tells Linux which interpreter to use when you run `./script.sh`.

What exactly is a .sh file?

A `.sh` file is a shell script — a text file where each line is a command (or part of one) for a shell program like Bash to execute in order. The `.sh` extension is a human-readable convention; Linux does not actually require it. What matters is the content and, when you execute it directly, the shebang line at the top.

Here is a minimal example. Create it with any editor, or straight from the terminal:

“`bash cat > hello.sh <<'EOF'

#!/bin/bash echo “Hello from a shell script!” echo “Today is: $(date)” EOF “`

That file now contains:

“`bash

#!/bin/bash echo “Hello from a shell script!” echo “Today is: $(date)” “`

The first line, `#!/bin/bash`, is the shebang (more on it below). The remaining lines are ordinary commands. Running the file means asking the shell to execute those commands in sequence.

What is the shebang line and why does it matter?

The shebang is the very first line of a script, starting with `#!` followed by the path to an interpreter:

“`bash

#!/bin/bash # use the Bash shell

#!/bin/sh # use the system’s POSIX shell

#!/usr/bin/env bash # find bash via PATH (more portable) “`

When you run a script *directly* with `./script.sh`, Linux reads this line to decide which program should interpret the file. Without a shebang, the system falls back to your current shell, which can cause subtle bugs if the script relies on Bash-specific features but gets run by `sh`.

The shebang is only consulted when you execute the file directly. If you call the interpreter yourself — `bash script.sh` — Bash runs the file regardless of what the shebang says, because you have already named the interpreter on the command line.

“`bash

#!/usr/bin/env bash # most portable shebang for Bash scripts echo “This runs under Bash no matter where Bash lives.” “`

How do I run a .sh file by making it executable?

This is the “proper” method for scripts you will run repeatedly. Two commands:

“`bash chmod +x hello.sh # grant the execute permission bit ./hello.sh # run it from the current directory “`

Expected output:

“`text Hello from a shell script! Today is: Tue Jun 30 09:14:02 UTC 2026 “`

`chmod +x` adds the execute bit to the file’s permissions. You only need to do this once per script — the bit stays set. After that, `./hello.sh` runs it any time.

You can confirm the bit is set by listing the file’s permissions:

“`bash ls -l hello.sh

“`

If you only want the owner to be able to execute it (tighter security), use:

“`bash chmod u+x hello.sh # execute permission for the owner only ./hello.sh “`

Why do I need the `./` in front?

When you type a bare command like `ls` or `git`, Linux searches the directories listed in your `PATH` environment variable to find the program. The current directory is deliberately not in `PATH`. If it were, an attacker could drop a malicious file named `ls` into a shared folder, and you would run it by accident just by typing `ls`.

So to run a script in the directory you are standing in, you must give Linux an explicit path. `./` means “right here, in the current directory”:

“`bash ./hello.sh # explicit: run hello.sh from here /home/ravi/scripts/hello.sh # absolute path also works from anywhere ~/scripts/hello.sh # ~ expands to your home directory “`

How do I run a .sh file by passing it to the interpreter?

The fastest method, especially for a script you will run once: call the interpreter and hand it the file as an argument. No `chmod` needed.

“`bash bash hello.sh # run with Bash sh hello.sh # run with the system POSIX shell “`

Both print the same output. Because you are running the *interpreter* (Bash or sh) and merely feeding it the file as text, the execute bit on the file is irrelevant — and the shebang line is ignored too.

Use `sh` only when the script is written for the POSIX shell. If it uses Bash-specific syntax (arrays, `[[ ]]`, `${var,,}`, etc.), run it with `bash` to avoid errors.

“`bash bash /home/ravi/scripts/backup.sh # full path works fine bash ./deploy.sh # relative path with ./ also fine “`

What does sourcing a script do?

There is a third way, and it behaves differently. Sourcing runs the script’s commands in your current shell instead of spawning a new one:

“`bash source hello.sh # long form . hello.sh # dot is shorthand for source “`

Why does this matter? A normally executed script runs in a child shell, so any variables it sets or directories it changes into disappear when it finishes. A sourced script changes your *current* session. This is exactly why you source things like `~/.bashrc` or a virtual environment activator:

“`bash . venv/bin/activate # modifies your current shell’s environment source ~/.bashrc # reloads your shell config in place “`

Rule of thumb: execute scripts that *do* a task; source scripts that are meant to *change your current shell*.

Which method should I use? (comparison table)

The `Permission denied` wall that stops nearly every beginner reveals a deliberate Linux security principle: a file being a script does not automatically make it runnable. Linux refuses to execute a file unless it has the execute permission bit set — precisely so that a malicious or accidental text file (say, something you just downloaded) cannot run itself. *You* must explicitly grant permission with `chmod +x`.

That is why `./script.sh` fails with `Permission denied` on a fresh script, but `bash script.sh` works on the very same file. When you call the interpreter directly, you are running Bash (which is already executable) and merely feeding it the file as text — no execute bit on the script is required. When you run `./script.sh`, you are asking Linux to execute the file itself, which demands the bit.

This gives you two clean options: grant the execute bit once (`chmod +x`, then `./script.sh` forever after) for scripts you trust and run often, or skip permissions entirely with `bash script.sh` for a one-off. Once you understand that “executable” is a permission you grant, not an inherent property of `.sh` files, the error and both ways around it stop being mysterious. It is also why you should glance at a downloaded script *before* you `chmod +x` it — running that command is you explicitly authorizing the file to execute.

Method Command Needs `chmod +x`? Runs in current shell? Best for
Executable + run `chmod +x script.sh` then `./script.sh` Yes (once) No (child shell) Scripts you run often
Pass to interpreter `bash script.sh` or `sh script.sh` No No (child shell) One-off runs, quick tests
Source it `source script.sh` or `. script.sh` No Yes Changing your current shell/env

How do I check that the script actually ran?

After running any command, the shell stores its exit status in the special variable `$?`. A value of `0` means success; anything else signals an error:

“`bash ./hello.sh echo $? # 0 means the script finished successfully “`

For scripts that produce side effects (creating files, starting services), verify the result directly:

“`bash ./backup.sh ls -lh /backups/ # confirm the backup file exists systemctl status nginx # confirm a service the script touched “`

To watch a longer script as it runs, add `set -x` near the top to echo each command before executing it — invaluable for debugging:

“`bash

#!/bin/bash set -x # print each command as it runs echo “Step 1” cp important.conf /etc/ # you’ll see this printed before it executes “`

What are the most common errors and how do I fix them?

Error message Cause Fix
`Permission denied` Execute bit not set `chmod +x script.sh` then `./script.sh` — or use `bash script.sh`
`command not found` No `./` prefix; dir not in PATH Use `./script.sh` or a full path
`bad interpreter` Bad shebang or Windows line endings Fix the shebang path; run `dos2unix script.sh`
`No such file or directory` Wrong path or `\r` line endings Check `ls`; convert line endings
`syntax error` Bash script run with `sh` Run with `bash script.sh` instead

“Permission denied”

“`bash ./hello.sh

“`

The execute bit is not set. Grant it, or sidestep it entirely:

“`bash chmod +x hello.sh && ./hello.sh # option 1: grant the bit bash hello.sh # option 2: feed it to bash “`

“command not found”

“`bash hello.sh

“`

You ran it without a path, so the shell searched `PATH` and found nothing. Add `./`:

“`bash ./hello.sh “`

“bad interpreter” or `\r` Windows line endings

If you created or edited the script on Windows, it may have carriage-return (`\r`) line endings that break the shebang. The error often looks like this:

“`text ./deploy.sh: /bin/bash^M: bad interpreter: No such file or directory “`

That `^M` is the stray carriage return. Convert the file to Unix line endings:

“`bash dos2unix deploy.sh # cleanest fix if dos2unix is installed sed -i ‘s/\r$//’ deploy.sh # works without installing anything “`

Then check the shebang path is correct (`#!/bin/bash`, not `#!/bin/bash ` with a trailing space).

When do I need to run a script with sudo?

If a script performs administrative actions — installing packages, editing files in `/etc`, restarting services — it needs root privileges. Run it with `sudo`:

“`bash sudo ./install.sh # run an executable script as root sudo bash install.sh # or pass it to bash as root “`

A caution: `sudo` runs as a *different user* (root) with a different environment. Variables from your current shell, and `~` expanding to *your* home, may behave differently. Never `sudo` a script you have not read — you are handing it complete control of the machine. Open it first:

“`bash less install.sh # read before you run with elevated privileges “`

Only escalate the parts that need it. A well-written script often uses `sudo` *internally* on specific lines rather than expecting you to run the whole thing as root.


Running scripts on your own Linux server? DarazHost Linux SSD VPS and dedicated servers give you full root SSH access to write, permission, and run shell scripts for automation, deployment, and admin tasks. Schedule them with cron, lean on guaranteed resources in a real Linux environment, and get 24/7 support when a script misbehaves at 3 a.m. It is the difference between practicing on a sandbox and running production automation on infrastructure you control.


Putting it all together: a practical workflow

Here is the full sequence you will use day to day — write, permission, run, verify:

“`bash

cat > deploy.sh <<'EOF'

#!/usr/bin/env bash set -e # stop on the first error echo “Pulling latest code…” git pull origin main echo “Restarting service…” sudo systemctl restart myapp echo “Done.” EOF

chmod +x deploy.sh

./deploy.sh

echo “Exit status: $?” systemctl status myapp –no-pager “`

For a quick one-off where you do not want to touch permissions at all, the whole thing collapses to one line:

“`bash bash deploy.sh “`

That is genuinely all there is to running a `.sh` file in Linux. Master these three methods — `./script.sh`, `bash script.sh`, and `source script.sh` — and you can run any shell script anyone hands you, and fix it when it breaks.

This tutorial is part of our Linux Server Administration: The Complete Guide to Managing Linux Servers pillar. To go deeper, explore how scripts are built, how the file permissions you just used actually work, and the commands these scripts are made of.

Frequently Asked Questions

Do I have to name my script with a `.sh` extension? No. Linux determines how to run a file by its shebang line and execute permissions, not its name. The `.sh` extension is purely a convention to signal “this is a shell script” to humans. A script named `backup` works exactly like `backup.sh`.

What is the difference between `bash script.sh` and `./script.sh`? `bash script.sh` runs the Bash interpreter and feeds it your file as text, so no execute permission is needed and the shebang is ignored. `./script.sh` asks Linux to execute the file itself, which requires the execute bit (`chmod +x`) and uses the shebang to pick the interpreter.

Why does my script work with `bash script.sh` but fail with `./script.sh`? Because the file lacks the execute permission bit. Run `chmod +x script.sh` once, and `./script.sh` will work from then on. The `bash` method never checks that bit, which is why it succeeded.

What does `source script.sh` do differently? Sourcing runs the script’s commands in your *current* shell rather than a new child process, so variable changes and directory changes persist in your session. Use it for environment setup files like `.bashrc`; use regular execution for scripts that just perform a task.

My script gives a “bad interpreter” error — what is wrong? The script almost certainly has Windows-style carriage-return line endings, which corrupt the shebang line. Fix it with `dos2unix script.sh` or `sed -i ‘s/\r$//’ script.sh`, then run it again.

About the Author

Leave a Reply