如何检查 Bash shell 脚本中是否存在目录?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/59838/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 17:36:53  来源:igfitidea点击:

How can I check if a directory exists in a Bash shell script?

bashshellunixposix

提问by Grundlefleck

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

在 Bash shell 脚本中,什么命令可用于检查目录是否存在?

回答by Grundlefleck

To check if a directory exists in a shell script, you can use the following:

要检查 shell 脚本中是否存在目录,您可以使用以下命令:

if [ -d "$DIRECTORY" ]; then
  # Control will enter here if $DIRECTORY exists.
fi

Or to check if a directory doesn't exist:

或者检查目录是否不存在:

if [ ! -d "$DIRECTORY" ]; then
  # Control will enter here if $DIRECTORY doesn't exist.
fi


However, as Jon Ericsonpoints out, subsequent commands may not work as intended if you do not take into account that a symbolic link to a directory will also pass this check. E.g. running this:

但是,正如Jon Ericson指出的那样,如果您不考虑到目录的符号链接也会通过此检查,则后续命令可能无法按预期工作。例如运行这个:

ln -s "$ACTUAL_DIR" "$SYMLINK"
if [ -d "$SYMLINK" ]; then 
  rmdir "$SYMLINK" 
fi

Will produce the error message:

会产生错误信息:

rmdir: failed to remove `symlink': Not a directory

So symbolic links may have to be treated differently, if subsequent commands expect directories:

因此,如果后续命令需要目录,则可能必须对符号链接进行不同的处理:

if [ -d "$LINK_OR_DIR" ]; then 
  if [ -L "$LINK_OR_DIR" ]; then
    # It is a symlink!
    # Symbolic link specific commands go here.
    rm "$LINK_OR_DIR"
  else
    # It's a directory!
    # Directory command goes here.
    rmdir "$LINK_OR_DIR"
  fi
fi


Take particular note of the double-quotes used to wrap the variables. The reason for this is explained by 8jean in another answer.

请特别注意用于包装变量的双引号。8jean在另一个答案中解释了这个原因。

If the variables contain spaces or other unusual characters it will probably cause the script to fail.

如果变量包含空格或其他异常字符,则可能会导致脚本失败。

回答by 8jean

Remember to always wrap variables in double quotes when referencing them in a Bash script. Kids these days grow up with the idea that they can have spaces and lots of other funny characters in their directory names. (Spaces! Back in my days, we didn't have no fancy spaces! ;))

请记住,在 Bash 脚本中引用变量时,始终将它们用双引号括起来。这些天的孩子们在他们的目录名称中可以有空格和许多其他有趣的字符的想法长大。(空格!在我的时代,我们没有花哨的空格!;))

One day, one of those kids will run your script with $DIRECTORYset to "My M0viez"and your script will blow up. You don't want that. So use this.

有一天,其中一个孩子会使用$DIRECTORYset to运行您的脚本,"My M0viez"而您的脚本会爆炸。你不想那样。所以用这个。

if [ -d "$DIRECTORY" ]; then
    # Will enter here if $DIRECTORY exists, even if it contains spaces
fi

回答by Jon Ericson

Note the -dtest can produce some surprising results:

请注意-d测试会产生一些令人惊讶的结果:

$ ln -s tmp/ t
$ if [ -d t ]; then rmdir t; fi
rmdir: directory "t": Path component not a directory

File under: "When is a directory not a directory?" The answer: "When it's a symlink to a directory." A slightly more thorough test:

文件在:“什么时候目录不是目录?” 答案是:“当它是一个目录的符号链接时。” 稍微更彻底的测试:

if [ -d t ]; then 
   if [ -L t ]; then 
      rm t
   else 
      rmdir t
   fi
fi

You can find more information in the Bash manual on Bash conditional expressionsand the [builtin commandand the [[compound commmand.

您可以在 Bash 手册中找到有关Bash 条件表达式[内置命令以及[[复合命令的更多信息。

回答by yukondude

I find the double-bracketversion of testmakes writing logic tests more natural:

我发现双括号版本test使编写逻辑测试更自然:

if [[ -d "${DIRECTORY}" && ! -L "${DIRECTORY}" ]] ; then
    echo "It's a bona-fide directory"
fi

回答by elmarco

Shorter form:

更短的形式:

[ -d "$DIR" ] && echo "Yes"

回答by Jorge Barroso

To check if a directory exists you can use a simple ifstructure like this:

要检查目录是否存在,您可以使用这样的简单if结构:

if [ -d directory/path to a directory ] ; then
# Things to do

else #if needed #also: elif [new condition]
# Things to do
fi

You can also do it in the negative:

你也可以否定它:

if [ ! -d directory/path to a directory ] ; then
# Things to do when not an existing directory

Note: Be careful. Leave empty spaces on either side of both opening and closing braces.

注意:小心。在左大括号和右大括号的两侧留空。

With the same syntax you can use:

使用相同的语法,您可以使用:

-e: any kind of archive

-f: file

-h: symbolic link

-r: readable file

-w: writable file

-x: executable file

-s: file size greater than zero

回答by yoctotutor.com

  1. A simple script to test if a directory or file is present or not:

    if [ -d /home/ram/dir ]   # For file "if [-f /home/rama/file]"
    then
        echo "dir present"
    else
        echo "dir not present"
    fi
    
  2. A simple script to check whether the directory is present or not:

    mkdir tempdir   # If you want to check file use touch instead of mkdir
    ret=$?
    if [ "$ret" == "0" ]
    then
        echo "dir present"
    else
        echo "dir not present"
    fi
    

    The above scripts will check if the directory is present or not

    $?if the last command is a success it returns "0", else a non-zero value. Suppose tempdiris already present. Then mkdir tempdirwill give an error like below:

    mkdir: cannot create directory ‘tempdir': File exists

  1. 一个用于测试目录或文件是否存在的简单脚本:

    if [ -d /home/ram/dir ]   # For file "if [-f /home/rama/file]"
    then
        echo "dir present"
    else
        echo "dir not present"
    fi
    
  2. 检查目录是否存在的简单脚本:

    mkdir tempdir   # If you want to check file use touch instead of mkdir
    ret=$?
    if [ "$ret" == "0" ]
    then
        echo "dir present"
    else
        echo "dir not present"
    fi
    

    上面的脚本将检查目录是否存在

    $?如果最后一个命令成功,则返回“0”,否则返回非零值。假设tempdir已经存在。然后mkdir tempdir会报错如下:

    mkdir: 无法创建目录 'tempdir': 文件存在

回答by kenorb

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

您可以使用test -d(参见man test)。

-d fileTrue if file exists and is a directory.

-d file如果文件存在并且是目录,则为真。

For example:

例如:

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

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

注意:该test命令与条件表达式[(参见:)相同man [,因此它可以跨 shell 脚本移植。

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

[- 这是testbuiltin的同义词,但最后一个参数必须是文字],以匹配开头[.

For possible options or further help, check:

有关可能的选项或进一步的帮助,请检查:

  • help [
  • help test
  • man testor man [
  • help [
  • help test
  • man test或者 man [

回答by kenorb

Or for something completely useless:

或者对于完全无用的东西:

[ -d . ] || echo "No"

回答by Henk Langeveld

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.

这种方法的好处是我不必考虑好的错误消息。

cdwill give me a standard one line message to standard erroralready. It will also give more information than I will be able to provide. By performing the cdinside 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.

cd会给我一个标准的单行消息到标准错误。它还将提供比我能够提供的更多信息。通过cd在 subshel​​l 内部执行( ... ),该命令不会影响调用者的当前目录。如果目录存在,这个子shell和函数只是一个空操作。

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.

接下来是我们传递给cd:的参数${1:?pathname expected}。这是一种更复杂的参数替换形式,将在下面更详细地解释。

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.

Tl; dr:如果传入这个函数的字符串是空的,我们再次退出子shell( ... )并从函数返回给定的错误信息。



Quoting from the ksh93man page:

ksh93手册页引用:

${parameter:?word}

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

如果 parameter已设置且为非空,则替换其值;否则,打印word并退出 shell(如果不是交互式的)。如果word省略,则打印标准消息。

and

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

如果:上述表达式中省略了冒号,则 shell 仅检查是否设置了参数。

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

这里的措辞是 shell 文档所特有的,word可以指任何合理的字符串,包括空格。

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

在这种特殊情况下,我知道标准错误消息1: parameter not set是不够的,所以我放大了我们在这里期望的值类型 -pathname目录的类型。

A philosophical 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.

shell 不是面向对象的语言,所以消息说pathname, not directory。在这个层面上,我宁愿保持简单——函数的参数只是字符串。