Bash error: Is a directory

Bash prints "Is a directory" when you try to read, execute, or redirect a directory as if it were a regular file.

Error String

bash: /path: Is a directory

Tldr

A command expected a file and got a directory. Common cases: `cat /var/log`, `./somedir` (no slash needed but the entry was a dir), or `> /tmp` where `/tmp` already exists as a directory. Check the path and add the filename you actually want.

Cause

Often a missing trailing filename in a path constructed by string concatenation: `"$LOGDIR$LOGNAME"` where `$LOGNAME` is empty.

Repro

cat /var/log                 # bash: /var/log: Is a directory

Fix

cat /var/log/syslog
# Or list contents:
ls /var/log

# Defensive guard:
[ -f "$path" ] || { echo "$path is not a file" >&2; exit 1; }

Explanation

Pair construction of paths with assertions: `test -f`, `test -d`, or a regex on the final segment. Catching the wrong-type case early avoids confusing downstream errors.

Faq

Q

Why does the redirection fail rather than create a file?

A

The path already exists as a directory, and the kernel refuses to open a directory for writing.

Q

How do I copy a directory intentionally?

A

Use `cp -r source dest` (or `cp -a` to preserve attributes); plain `cp` refuses directories by design.

Deep Dive

Heading

Where the directory sneaks in

Body

The three common sources are a redirection target that is a directory (`> /var/log` instead of `> /var/log/app.log`), a `cp`/`mv` destination built from a variable with a trailing slash and an empty basename, and a `cat` over a glob that matched directories as well as files. Because the variable expands to something that looks plausible, the mistake is usually one missing component: `dest=$dir/$name` where `$name` is empty produces the directory itself.

Heading

Guard the path before writing

Body

Test explicitly: `[ -d "$path" ] && { echo "$path is a directory" >&2; exit 1; }`, and use `[ -n "$name" ]` to reject an empty basename before composing the path. For copies, `cp -r` handles directories deliberately, so decide which behaviour you want rather than letting the error decide for you. When iterating a glob, filter with `[ -f "$f" ] || continue`, since an unmatched glob otherwise passes the literal pattern through and `nullglob` changes that behaviour again.

Checklist

Print the fully expanded path just before the failing command.

Check for an empty variable that leaves only the directory part.

Add a `[ -f "$path" ]` or `[ -d "$path" ]` guard with a clear message.

Filter globs so directories never reach a file-only command.