检查shell脚本中是否存在目录

时间:2008-09-12 20:06:26

标签: shell unix posix

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

36 个答案:

答案 0 :(得分:4731)

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

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

或检查目录是否不存在:

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

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

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

将产生错误消息:

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

因此,如果后续命令需要目录,则必须区别对待符号链接:

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

特别注意用于包装变量的双引号,其原因由8jean in another answer解释。

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

答案 1 :(得分:499)

请记住在引用变量时始终将变量用双引号括起来 一个bash脚本。这些天孩子们长大了,他们的目录名称中可以有空格和许多其他有趣的字符。 (太空!回到我的日子,我们没有任何奇特的空间!;))

有一天,其中一个孩子将运行您的脚本,$DIRECTORY设置为"My M0viez",您的脚本将会爆炸。你不希望这样。所以使用它。

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

答案 2 :(得分:218)

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

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

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

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

您可以在Bash conditional expressions[ builtin command以及[[ compound commmand上的Bash手册中找到更多信息。

答案 3 :(得分:207)

我发现test版本if [[ -d "${DIRECTORY}" && ! -L "${DIRECTORY}" ]] ; then echo "It's a bona-fide directory" fi 使编写逻辑测试更自然:

{{1}}

答案 4 :(得分:142)

缩短形式:

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

答案 5 :(得分:124)

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

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

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

您也可以在否定

中执行此操作
if [ ! -d directory/path to a directory ] ; then
# things to do when not an existing directory

注意:小心,在打开和关闭括号的两侧留空空格。

使用相同的语法:

-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 

答案 6 :(得分:96)

if [ -d "$DIRECTORY" ]; then  
    # Here if $DIRECTORY exists  
fi

答案 7 :(得分:82)

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

  

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

例如:

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

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

  

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

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

  • help [
  • help test
  • man testman [

答案 8 :(得分:72)

  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':文件存在

答案 9 :(得分:54)

或者完全没用的东西:

[ -d . ] || echo "No"

答案 10 :(得分:47)

这是一个非常实用的习语:

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

我通常将它包装在一个函数中:

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

或者:

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

这种方法的好处在于我不必考虑好的错误信息。

cd会给stderr标准的一行消息。它还将提供比我能提供的更多信息。通过在子shell cd内执行( ... ),该命令不会影响调用者的当前目录。如果目录存在,则此子shell和函数只是一个无操作。

接下来是我们传递给cd${1:?pathname expected}的论点。这是一种更精细的参数替换形式,下面将对此进行详细说明。

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


ksh93手册页引用:

${parameter:?word}
  

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

  

如果从上面的表达式中省略了冒号:,那么   shell只检查参数是否设置。

这里的措辞是shell文档所特有的,正如word可能引用的那样 任何合理的字符串,包括空格。

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

philosphical note: shell不是面向对象的语言,因此消息显示为pathname,而不是directory。在这个级别,我宁愿保持简单 - 函数的参数只是字符串。

答案 11 :(得分:36)

if [ -d "$Directory" -a -w "$Directory" ]
then
    #Statements
fi

上面的代码检查目录是否存在以及它是否可写。

答案 12 :(得分:25)

在bash提示符下输入此代码

if [ -d "$DIRECTORY" ]; then
  # if true this block of code will execute
fi

答案 13 :(得分:20)

使用find

的更多功能
  • 检查子目录中是否存在文件夹:

    found=`find -type d -name "myDirectory"`
    if [ -n "$found"]
    then
        # The variable 'found' contains the full path where "myDirectory" is.
        # It may contain several lines if there are several folders named "myDirectory".
    fi
    
  • 根据当前目录中的模式检查是否存在一个或多个文件夹:

    found=`find -maxdepth 1 -type d -name "my*"`
    if [ -n "$found"]
    then
        # The variable 'found' contains the full path where folders "my*" have been found.
    fi
    
  • 两种组合。在以下示例中,它检查当前目录中是否存在该文件夹:

    found=`find -maxdepth 1 -type d -name "myDirectory"`
    if [ -n "$found"]
    then
        # The variable 'found' is not empty => "myDirectory"` exists.
    fi
    

答案 14 :(得分:19)

实际上,您应该使用多种工具来获得防弹方法:

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

只要您使用"${}",就无需担心空格和特殊字符。

请注意,[[]]不像[]那样可移植,但由于大多数人都使用现代版本的Bash(因为毕竟大多数人甚至不使用命令行:-p) ,好处大于麻烦。

答案 15 :(得分:16)

要检查多个目录,请使用以下代码:

if [ -d "$DIRECTORY1" ] && [ -d "$DIRECTORY2" ] then
    # Things to do
fi

答案 16 :(得分:16)

你有没有考虑过在if做你想做的事情,而不是在你跳跃之前先看一下?

IE,如果您想在输入之前检查目录是否存在,请尝试这样做:

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

如果您提供给pushd的路径存在,则您将输入该路径,并且它将以0退出,这意味着该语句的then部分将会执行。如果它不存在,则不会发生任何事情(除了某些输出说该目录不存在,这可能是一个有用的副作用,无论如何调试)。

似乎比这更好,这需要重复自己:

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

同样适用于cdmvrm等等...如果您尝试使用不存在的文件,他们会退出错误并打印一条消息,表明它不存在,并且您的then块将被跳过。如果您对存在的文件进行尝试,该命令将执行并退出状态为0,允许您的then块执行。

答案 17 :(得分:15)

检查目录是否存在,否则制作一个

[ -d "$DIRECTORY" ] || mkdir $DIRECTORY

答案 18 :(得分:14)

[[ -d "$DIR" && ! -L "$DIR" ]] && echo "It's a directory and not a symbolic link"
  

N.B:引用变量是一种很好的做法。

答案 19 :(得分:12)

[ -d ~/Desktop/TEMPORAL/ ] && echo "DIRECTORY EXISTS" || echo "DIRECTORY DOES NOT EXIST"

答案 20 :(得分:11)

This answer包装为shell脚本

实施例

function show_help()
{
  IT=$(CAT <<EOF

  usage: DIR
  output: YES or NO, depending on whether or not the directory exists.

  )
  echo "$IT"
  exit
}

if [ "$1" == "help" ]
then
  show_help
fi
if [ -z "$1" ]
then
  show_help
fi

DIR=$1
if [ -d $DIR ]; then 
   echo "YES";
   exit;
fi
echo "NO";

is_dir

final String SALT = "any strange string that you like";

String mySha1String = DigestUtils.sha1Hex(myString + SALT);

答案 21 :(得分:10)

使用-e检查将检查文件,包括目录。

if [ -e ${FILE_PATH_AND_NAME} ]
then
    echo "The file or directory exists."
fi

答案 22 :(得分:9)

DIRECTORY=/tmp

if [ -d "$DIRECTORY" ]; then
    echo "Exists"
fi

Try online

答案 23 :(得分:8)

根据Jonathan评论:

如果你想创建目录并且它还不存在,那么最简单的方法是使用function wildcard(input) { var output = [], cases = [], wilds = [], patts = [], masks = []; var bits = groupCases(cases); for (var i = 0; i <= bits; i++) wilds[i] = []; wildStrings(bits); convertStrings(wilds, patts, "-01", "110"); convertStrings(wilds, masks, "-01", "011"); for (var c = 0; c < cases.length; c++) { for (var i = 0, j = Math.pow(2, bits); i <= bits; i++, j /= 2) { for (var k = 0; k < patts[i].length; k++) { var patt = patts[i][k]; var mask = masks[i][k]; var matches = []; for (var d = 0; d < cases[c].nums.length; d++) { var num = cases[c].nums[d]; if (((num ^ patt) & mask) == mask) matches.push(d); } if (matches.length == j) { output.push(wilds[i][k] + " " + cases[c].id); for (var l = j - 1; l >= 0; l--) cases[c].nums.splice(matches[l], 1); } } } } return output; function groupCases(cases) { var max = 0; for (var i = 0; i < input.length; i++) { var num = parseInt(input[i], 2); if (num > max) max = num; var id = input[i].slice(input[i].indexOf(" ") + 1); var pos = 0; while (cases[pos] != undefined && cases[pos].id != id) ++pos; if (cases[pos] == undefined) cases[pos] = {id: id, nums: []}; cases[pos].nums.push(num); } return Math.ceil(Math.log(max) / Math.log(2)); } function wildStrings(len, wild, str) { wild = wild || 0; str = str || ""; for (var i = 0; i < 3; i++) { var w = (i == 0) ? 1 : 0; var s = str + ["-","0","1"][i]; if (len > 1) wildStrings(len - 1, wild + w, s) else wilds[bits - wild - w].push(s); } } function convertStrings(input, output, from, to) { for (var i = 0; i < input.length; i++) { output[i] = []; for (var j = 0; j < input[i].length; j++) { var str = input[i][j], s = ""; for (var k = 0; k < str.length; k++) { s += to.charAt(from.indexOf(str.charAt(k))); } output[i].push(parseInt(s, 2)); } } } } var a = ["000 CASE_01", "001 CASE_02", "010 CASE_03", "1010 CASE_04", "011 CASE_02", "100 CASE_02", "1110 CASE_04", "101 CASE_01", "110 CASE_01", "1100 CASE_04", "1000 CASE_04", "111 CASE_01"]; var w = wildcard(a); document.write(w.length + " wildcards:<BR><PRE>"); for (var i in w) document.write(w[i] + "<BR>");创建目录 - 以及路径上任何缺少的目录 - 如果目录已经存在则不会失败存在,所以你可以用:

一次完成所有操作
mkdir -p

答案 24 :(得分:7)

if [ -d "$DIRECTORY" ]; then
    # Will enter here if $DIRECTORY exists
fi

这不完全正确...... 如果要转到该目录,还需要具有该目录的执行权限。也许你还需要拥有写权利。

Therfore:

if [ -d "$DIRECTORY" ] && [ -x "$DIRECTORY" ] ; then
    # ... to go to that directory (even if DIRECTORY is a link)
    cd $DIRECTORY
    pwd
fi

if [ -d "$DIRECTORY" ] && [ -w "$DIRECTORY" ] ; then
    # ... to go to that directory and write something there (even if DIRECTORY is a link)
    cd $DIRECTORY
    touch foobar
fi

答案 25 :(得分:6)

ls命令与-l(长列表)选项一起返回有关文件和目录的属性信息。
特别是ls -l输出的第一个字符通常是d-(短划线)。如果d列出的是肯定的目录。

以下命令只会在一行中告诉您给定的 ISDIR 变量是否包含目录的路径:

[[ $(ls -ld "$ISDIR" | cut -c1) == 'd' ]] &&
    echo "YES, $ISDIR is a directory." || 
    echo "Sorry, $ISDIR is not a directory"

实际用法:

    [claudio@nowhere ~]$ ISDIR="$HOME/Music" 
    [claudio@nowhere ~]$ ls -ld "$ISDIR"
    drwxr-xr-x. 2 claudio claudio 4096 Aug 23 00:02 /home/claudio/Music
    [claudio@nowhere ~]$ [[ $(ls -ld "$ISDIR" | cut -c1) == 'd' ]] && 
        echo "YES, $ISDIR is a directory." ||
        echo "Sorry, $ISDIR is not a directory"
    YES, /home/claudio/Music is a directory.

    [claudio@nowhere ~]$ touch "empty file.txt"
    [claudio@nowhere ~]$ ISDIR="$HOME/empty file.txt" 
    [claudio@nowhere ~]$ [[ $(ls -ld "$ISDIR" | cut -c1) == 'd' ]] && 
        echo "YES, $ISDIR is a directory." || 
        echo "Sorry, $ISDIR is not a directoy"
    Sorry, /home/claudio/empty file.txt is not a directory

答案 26 :(得分:5)

(1)

[ -d Piyush_Drv1 ] && echo ""Exists"" || echo "Not Exists"

(2)

[ `find . -type d -name Piyush_Drv1 -print | wc -l` -eq 1 ] && echo Exists || echo "Not Exists"

(3)

[[ -d run_dir  && ! -L run_dir ]] && echo Exists || echo "Not Exists"

如果发现上述方法之一存在问题。

使用ls命令;目录不存在的情况 - 显示错误消息

$ [[ls -ld SAMPLE_DIR| grep ^d | wc -l -eq 1]]&amp;&amp;回声存在||不存在 -ksh:not:找不到[没有这样的文件或目录]

答案 27 :(得分:5)

如果要检查目录是否存在,无论它是真实目录还是符号链接,请使用:

ls $DIR
if [ $? != 0 ]; then
        echo "Directory $DIR already exists!"
        exit 1;
fi
echo "Directory $DIR does not exist..."

说明:如果目录或符号链接不存在,“ls”命令会给出错误“ls:/ x:没有这样的文件或目录”,并设置返回代码,您可以通过“$?”检索该代码。 ,非null(通常为“1”)。 确保在调用“ls”后直接检查返回码。

答案 28 :(得分:5)

file="foo" 
if [[ -e "$file" ]]; then echo "File Exists"; fi;

答案 29 :(得分:4)

可以使用以下查找,

find . -type d -name dirname -prune -print

答案 30 :(得分:4)

Git Bash + Dropbox + Windows:

其他解决方案都没有适用于我的Dropbox文件夹, 这很奇怪,因为我可以把它推到Dropbox符号路径。

#!/bin/bash

dbox="~/Dropbox/"
result=0
prv=$(pwd) && eval "cd $dbox" && result=1 && cd "$prv"
echo $result

read -p "Press Enter To Continue:"

您可能想知道如何从bash成功导航到Dropbox。所以这里的脚本是完整的。

https://pastebin.com/QF2Exmpn

答案 31 :(得分:4)

那里有很好的解决方案,但如果你不在正确的目录中,最终每个脚本都会失败。所以这样的代码:

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
只有在执行时您才会在具有您要检查的子目录的目录中成功执行

我理解这样的初始问题:验证目录是否存在,而不管用户在文件系统中的位置如何。所以使用命令&#39; find&#39;可能会做的伎俩:

dir=" "
echo "Input directory name to search for:"
read dir
find $HOME -name $dir -type d

这个解决方案很好,因为它允许使用通配符,这是搜索文件/目录时的一个有用功能。唯一的问题是,如果搜索到的目录不存在,则“找到”&#39;命令将不打印任何stdout(不是一个优雅的解决方案,我的口味),并将有一个零退出。也许有人可以改进这一点。

答案 32 :(得分:4)

file程序怎么样。 考虑到所有目录也是linux中的文件,发出以下命令就足够了:

file $directory_name

正在检查不存在的文件:file blah

输出: cannot open 'blah' (No such file or directory)

检查现有目录:file bluh

输出: bluh: directory

答案 33 :(得分:2)

以三元形式,

[ -d "$directory" ] && echo "exist" || echo "not exist"

并通过测试

test -d "$directory" && echo "exist" || echo "not exist"

答案 34 :(得分:2)

来自脚本文件myScript.sh:

if [ -d /home/ec2-user/apache-tomcat-8.5.5/webapps/Gene\ Directory ]; then 
   echo "Directory exists!"
   echo "Great"
fi 

OR

if [ -d '/home/ec2-user/apache-tomcat-8.5.5/webapps/Gene Directory' ]; then 
   echo "Directory exists!"
   echo "Great"
fi 

答案 35 :(得分:0)

只是'[-d]'和'[-h]'选项的替代方法;您可以使用stat来获取文件类型并进行解析。

#! /bin/bash
MY_DIR=$1
NODE_TYPE=$(stat -c '%F' ${MY_DIR} 2>/dev/null)
case "${NODE_TYPE}" in
        "directory") echo $MY_DIR;;
    "symbolic link") echo $(readlink $MY_DIR);;
                 "") echo "$MY_DIR does not exist";;
                  *) echo "$NODE_TYPE is unsupported";;
esac
exit 0

测试数据:

$ mkdir tmp
$ ln -s tmp derp
$ touch a.txt
$ ./dir.sh tmp
tmp
$ ./dir.sh derp
tmp
$ ./dir.sh a.txt
regular file is unsupported
$ ./dir.sh god
god does not exist
相关问题