Check if a directory exists in a shell script

2018-12-31 14:29发布

What command can be used to check if a directory exists or not, within a shell script?

标签: shell unix posix
30条回答
公子世无双
2楼-- · 2018-12-31 15:06

Here's a very pragmatic idiom:

(cd $dir) || return # is this a directory,
                    # and do we have access?

I typically wrap it in a function:

can_use_as_dir() { 
    (cd ${1:?pathname expected}) || return
}

Or:

assert_dir_access() { 
    (cd ${1:?pathname expected}) || exit
}

The nice thing about this approach is that I do not have to think of a good error message.

cd will give me a standard one line message to stderr already. It will also give more information than I will be able to provide. By performing the cd inside a subshell ( ... ), the command does not affect the current directory of the caller. If the directory exists, this subshell and the function are just a no-op.

Next is the argument that we pass to cd: ${1:?pathname expected}. This is a more elaborate form of parameter substitution which is explained in more detail below.

Tl;dr: If the string passed into this function is empty, we again exit from the subshell ( ... ) and return from the function with the given error message.


Quoting from the ksh93 man page:

${parameter:?word}

If parameter is set and is non-null then substitute its value; otherwise, print word and exit from the shell (if not interactive). If word is omitted then a standard message is printed.

and

If the colon : is omitted from the above expressions, then the shell only checks whether parameter is set or not.

The phrasing here is peculiar to the shell documentation, as word may refer to any reasonable string, including whitespace.

In this particular case, I know that the standard error message 1: parameter not set is not sufficient, so I zoom in on the type of value that we expect here - the pathname of a directory.

A philosphical note: The shell is not an object oriented language, so the message says pathname, not directory. At this level, I'd rather keep it simple - the arguments to a function are just strings.

查看更多
与君花间醉酒
3楼-- · 2018-12-31 15:06
if [ -d "$Directory" -a -w "$Directory" ]
then
    #Statements
fi

The above code checks if the directory exists and if it is writable.

查看更多
与风俱净
4楼-- · 2018-12-31 15:08

You can use test -d (see man test).

-d file True if file exists and is a directory.

For example:

test -d "/etc" && echo Exists || echo Does not exist

Note: The test command is same as conditional expression [ (see: man [), so it's portable across shell scripts.

[ - This is a synonym for the test builtin, but the last argument must, be a literal ], to match the opening [.

For possible options or further help, check:

  • help [
  • help test
  • man test or man [
查看更多
梦醉为红颜
5楼-- · 2018-12-31 15:08

Actually, you should use several tools to get a bulletproof approach:

DIR_PATH=`readlink -f "${the_stuff_you_test}"` # Get rid of symlinks and get abs path
if [[ -d "${DIR_PATH}" ]] ; Then # now you're testing
    echo "It's a dir";
fi

No need to worry about spaces and special characters as long as you use "${}".

Note that [[]] is not as portable as [], but since most people work with modern versions of Bash (since after all, most people don't even work with command line :-p), the benefit is greater than the trouble.

查看更多
余生无你
6楼-- · 2018-12-31 15:09

Have you considered just doing whatever you want to do in the if rather than looking before you leap?

IE, if you want to check for the existence of a directory before you enter it, try just doing this:

if pushd /path/you/want/to/enter; then
    # commands you want to run in this directory
    popd
fi

If the path you give to pushd exists, you'll enter it and it'll exit with 0, which means the then portion of the statement will execute. If it doesn't exist, nothing will happen (other than some output saying the directory doesn't exist, which is probably a helpful side-effect anyways for debugging).

Seems better than this, which requires repeating yourself:

if [ -d /path/you/want/to/enter ]; then
    pushd /path/you/want/to/enter
    # commands you want to run in this directory
    popd
fi

Same thing works with cd, mv, rm, etc... if you try them on files that don't exist, they'll exit with an error and print a message saying it doesn't exist, and your then block will be skipped. If you try them on files that do exist, the command will execute and exit with a status of 0, allowing your then block to execute.

查看更多
倾城一夜雪
7楼-- · 2018-12-31 15:09
[ -d ~/Desktop/TEMPORAL/ ] && echo "DIRECTORY EXISTS" || echo "DIRECTORY DOES NOT EXIST"
查看更多
登录 后发表回答