2

I am trying to write a simple program that checks if a given filename refers to a directory. But I keep getting an error saying that "bad interpreter: no such file or directory" when I run ./isdir.sh (This is the name of the script).

here is my code:

#!bin/sh

if [[ $# -ne 1 ]];then
    echo "Usage: $0 dir"
    exit 1
fi

dir="$1"
dirname = "$1"

if [[ ! -d "$dir" ]]; then
    echo "Error: directory $dir not found."
    exit 2
fi

if [[ -d "$dirname" ]]; then
    echo "$dirname is a directory."
    exit 3

ALSO, IMPORTANT QUESTION: How do I handle input values that contain spaces in them?

codeforester
  • 39,467
  • 16
  • 112
  • 140
Kat
  • 113
  • 1
  • 1
  • 6
  • 3
    The first line should probably read `#!/bin/sh` (missing slash), or even better `#!/bin/bash` as the `[[ ]]` construct works only in Bash. – Benjamin W. Feb 06 '17 at 02:41
  • To add to @BenjaminW.'s helpful comment: While it wouldn't have caught the shebang-line problem (`#!bin/sh` instead of `#!/bin/sh`), pasting your code at [shellcheck.net](http://shellcheck.net) would have revealed the `[[` problem and more. – mklement0 Feb 06 '17 at 03:24

1 Answers1

0

You could do this:

#!/bin/bash

if [[ $# -ne 1 ]]; then
  echo "Usage: $0 dir"
  exit 2
fi

dir="$1"
rc=1
if [[ -d "$dir" ]]; then
  # it is a directory
  rc=0
elif [[ -e "$dir" ]]; then
  echo "Error: '$dir' is not a directory"
else 
  echo "Error: directory '$dir' does not exist"
fi

exit "$rc"

  • Don't need the dirname variable.
  • The script is safe for directories that have white spaces or wild cards in their name as we have enclosed the variable in double quotes.
  • Exit code of 2 is a Unix standard for invalid argument error; exit 1 is all other errors. However, you can change the exit codes as per your need.

See this related post for more perspectives around this problem: Check if a directory exists in a shell script

Community
  • 1
  • 1
codeforester
  • 39,467
  • 16
  • 112
  • 140
  • 1
    `#!/bin/sh` might be a shell other than Bash and not support `[[ ]]`. And even if it is Bash, it is started in POSIX mode with a lot of probably undesired side effects. On my machine, `[[ ]]` isn't even recognized when I run Bash with `sh`. – Benjamin W. Feb 06 '17 at 03:11
  • 1
    I have updated my answer so that the script uses Bash. – codeforester Feb 06 '17 at 03:12
  • 2
    @codeforester You might want to remove "Tested with sh and it worked." from your answer, as this is dependent on the shell understanding `[[ ]]` tests, i.e. being Bash. Or you could use `[ ]` tests, which I think would work here. – Fred Feb 06 '17 at 03:26
  • It did work with `sh` on my Mac. I have updated the answer to avoid any confusion. – codeforester Feb 06 '17 at 03:28
  • Does this handle inputs with space in them? – Kat Feb 06 '17 at 04:01
  • Yes, it does. Please see the second bullet point in the answer. – codeforester Feb 06 '17 at 04:04
  • 1
    Re "it did work with `sh` on my Mac`": on macOS, `bash` acts as `sh`, and even though when invoked as `sh` it changes its behavior to be POSIX-compliant, it still leaves many nonstandard extensions - such as `[[ … ]]` enabled, which makes it a poor environment for testing portable scripts. The point is: To be portable, you mustn't use any features beyond those mandated by the [POSIX spec](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html). Among modern shells, `dash` - which act as `sh` on Ubuntu systems - comes closest to _only_ supporting POSIX features. – mklement0 Feb 06 '17 at 04:42
  • Exit codes: `2` is _not_ generally standardized, although `bash`, `ksh` and `dash` - but not `zsh` - use it to signal syntax errors when _builtins_ are (incorrectly) invoked. While `1` is a common exit code that is used in a wide variety of error scenarios, POSIX doesn't mandate it specifically, and utilities can set exit codes up to and including `255`; however, `127`, `126`, and `128` + signal number when terminated by a signal _are_ POSIX-mandated in certain scenarios - see http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_08_02 – mklement0 Feb 06 '17 at 06:26
  • Terminology: _whitespace_ (singular, typically spelled as one word) is the customary umbrella term to refer to characters such as spaces and tabs collectively. Similarly, _wildcard_ (one word) is customary. – mklement0 Feb 06 '17 at 06:27