# Control will enter here"/>

关于Unix:检查shell脚本中是否存在目录

关于Unix:检查shell脚本中是否存在目录

Check if a directory exists in a shell script

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


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

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

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

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

但是,正如jon ericson指出的那样,如果不考虑到指向目录的符号链接也将通过此检查,那么后续命令可能无法按预期工作。例如,运行此:

1
2
3
4
ln -s"$ACTUAL_DIR""$SYMLINK"
if [ -d"$SYMLINK" ]; then
  rmdir"$SYMLINK"
fi

将生成错误消息:

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

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

1
2
3
4
5
6
7
8
9
10
11
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在另一个答案中解释了这一点。

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


在中引用变量时,请记住始终用双引号括起来。一个BASH脚本。现在的孩子们都是这样成长的:他们的目录名中可以有空格和许多其他有趣的字符。(空间!在我的时代,我们没有美好的空间!;)

有一天,其中一个孩子会运行你的脚本,把$DIRECTORY设置为"My M0viez",你的脚本就会爆炸。你不想那样。所以用这个。

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

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

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

文件位于:"什么时候目录不是目录?"答案是:"当它是一个指向目录的符号链接时。"一个稍微更彻底的测试:

1
2
3
4
5
6
7
if [ -d t ]; then
   if [ -L t ]; then
      rm t
   else
      rmdir t
   fi
fi

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


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

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


较短形式:

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

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

1
2
3
4
5
6
if [ -d directory/path to a directory ] ; then
#Things to do

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

你也可以用否定的方式

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

注意:请小心,在左右两侧的大括号上都留有空格。

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

1
2
3
4
5
6
7
8
9
10
11
12
13
-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

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

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

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

例如:

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

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

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

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

  • help [
  • help test
  • man testman [

  • 测试dir或file是否存在的简单脚本:

    1
    2
    3
    4
    5
    6
    if [ -d /home/ram/dir ]   # for file"if [-f /home/rama/file]"
    then
        echo"dir present"
    else
        echo"dir not present"
    fi
  • 检查目录是否存在的简单脚本:

    1
    2
    3
    4
    5
    6
    7
    8
    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

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

    如果最后一个命令成功,则返回"0",否则返回非零值。假设tempdir已经存在,那么mkdir tempdir将给出如下错误:

    mkdir: cannot create directory ‘tempdir’: File exists


  • 或者完全无用的东西:

    1
    [ -d . ] || echo"No"

    这里有一个非常实用的习语:

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

    我通常用一个函数包装它:

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

    或:

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

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

    cd会给我一条标准的单行消息,发送给stderr。它还将提供我无法提供的更多信息。通过在子shell ( ... )中执行cd命令,该命令不会影响调用方的当前目录。如果目录存在,这个子shell和函数只是一个no-op。

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

    tl;dr:如果传递给这个函数的字符串是空的,那么我们再次从子shell ( ... )中退出,并返回带有给定错误消息的函数。

    引用ksh93手册:

    1
    ${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.

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

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

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

    哲学注释:shell不是面向对象的语言,因此消息称为pathname,而不是directory。在这个层次上,我宁愿保持简单——函数的参数只是字符串。


    1
    2
    3
    4
    if [ -d"$Directory" -a -w"$Directory" ]
    then
        #Statements
    fi

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


    在bash promt上键入此代码

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

    更多使用find的功能

    • 检查子目录中是否存在文件夹:

      1
      2
      3
      4
      5
      6
      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
    • 根据当前目录中的模式检查一个或多个文件夹是否存在:

      1
      2
      3
      4
      5
      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
    • 两种组合。在下面的示例中,它检查当前目录中是否存在文件夹:

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


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

    1
    2
    3
    4
    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),所以好处大于麻烦。


    你有没有考虑过在江户中做任何你想做的事情,而不是在你跳之前看?

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

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

    如果您给pushd的路径存在,您将进入它,它将与0一起退出,这意味着将执行语句的then部分。如果它不存在,就不会发生任何事情(除了一些输出说目录不存在,这对于调试来说可能是一个有帮助的副作用)。

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

    1
    2
    3
    4
    5
    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块。


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

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

    检查目录是否存在,否则创建一个目录

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

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

    N.B: Quoting variables is a good practice.


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

    这个答案总结成一个shell脚本

    实例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    $ is_dir ~                          
    YES

    $ is_dir /tmp                        
    YES

    $ is_dir ~/bin                      
    YES

    $ mkdir '/tmp/test me'

    $ is_dir '/tmp/test me'
    YES

    $ is_dir /asdf/asdf                  
    NO

    # Example of calling it in another script
    DIR=~/mydata
    if [ $(is_dir $DIR) =="NO" ]
    then
      echo"Folder doesnt exist: $DIR";
      exit;
    fi

    伊斯迪尔

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    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";

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

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

    根据乔纳森评论:

    如果您想创建目录,但它还不存在,那么最简单的方法是使用创建目录的mkdir -p—以及路径上丢失的任何目录—如果目录已经存在,则不会失败,因此您可以同时使用:

    1
    mkdir -p /some/directory/you/want/to/exist || exit 1

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

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

    因此:

    1
    2
    3
    4
    5
    if [ -d"$DIRECTORY" ] && [ -x"$DIRECTORY" ] ; then
        # ... to go to that directory (even if DIRECTORY is a link)
        cd $DIRECTORY
        pwd
    fi
    1
    2
    3
    4
    5
    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


    ls命令与-l选项(长列表)一起返回有关文件和目录的属性信息。尤其是ls -l输出的第一个字符,通常是d-破折号。如果是d,所列的目录是确定的。

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

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

    实际用途:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
        [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

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

    (1)

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

    (2)

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

    (3)

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

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

    使用ls命令;当目录不存在时,会显示一条错误消息。

    $[[ls -ld SAMPLE_DIR| grep ^d | wc -l-公式1]]&;&;echo exists not exists-ksh:not:未找到[没有此类文件或目录]


    如果要检查目录是否存在,无论它是真正的目录还是符号链接,请使用以下命令:

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

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


    很好的解决方案,但是如果您不在正确的目录中,最终每个脚本都会失败。所以代码如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    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

    只有在执行时,您所在的目录正好有一个子目录要检查,才会成功执行。

    我理解这样的初始问题:验证不管用户在文件系统中的位置如何,目录是否存在。因此,使用"find"命令可能会做到这一点:

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

    这个解决方案很好,因为它允许使用通配符,这是搜索文件/目录时的一个有用功能。唯一的问题是,如果搜索到的目录不存在,"find"命令将不打印任何内容到stdout(对于我来说这不是一个优雅的解决方案),并且仍然有一个零出口。也许有人可以改进这个。


    可以使用下面的find,

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

    Git Bash+Dropbox+窗口:

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

    1
    2
    3
    4
    5
    6
    7
    8
    #!/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


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

    file $directory_name

    检查不存在的文件:file blah

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

    正在检查现有目录:file bluh

    输出:bluh: directory


    以三元形式,

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

    随试

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

    从脚本文件myscript.sh:

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

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

    推荐阅读

      了解linux下常用命令?

      了解linux下常用命令?,工作,地址,系统,信息,命令,标准,目录,常用命令,操作,

      linux获取地址命令?

      linux获取地址命令?,地址,网络,信息,系统,设备,终端,命令,中心,管理,数字,lin

      linux的u盘启动命令?

      linux的u盘启动命令?,系统,电脑,工具,信息,软件,网上,名称,工作,设备,通用,从

      linux设置路由器命令?

      linux设置路由器命令?,网络,信息,代码,地址,电脑,工作,环境,系统,密码,路由,l

      基本linux命令面试题?

      基本linux命令面试题?,系统,情况,设备,实时,工具,分析,证书,时间,教育,认证,

      linux命令连接光驱?

      linux命令连接光驱?,系统,位置,设备,数据,电脑,服务,资料,盘中,智能,管理,Lin

      linuxlspv命令?

      linuxlspv命令?,系统,管理,软件,产品,统一,发行,技术,情况,环境,实时,aix查看

      linux下分区命令行?

      linux下分区命令行?,系统,工具,设备,信息,分区,情况,首次,名称,网络,命令,lin

      u进入linux命令行?

      u进入linux命令行?,系统,地址,服务,电脑,命令,管理,工作,首页,终端,目录,linu

      更改时间linux命令?

      更改时间linux命令?,时间,系统,命令,环境,网上,信息,资料,概念,位置,终端,lin

      linux命令行更改中文?

      linux命令行更改中文?,系统,环境,管理,国家,信息,软件,文化,设备,中文,命令,l

      linux打包zip命令?

      linux打包zip命令?,时间,文件,信息,名称,系统,技术,命令,文件夹,格式,目录,li

      linux的vsp命令?

      linux的vsp命令?,手机,系统,软件,状态,信息,设备,发行,平台,电脑,工作,如何在

      linux关机命令及例子?

      linux关机命令及例子?,系统,信息,命令,时间,代码,用户,表示,指令,方式,提示,l

      linux命令行模式清页?

      linux命令行模式清页?,工作,系统,命令,信息,地址,目录,内容,文件,操作,功能,l

      linux更改账户名命令?

      linux更改账户名命令?,密码,系统,代码,命令,基础,信息,软件,用户,用户名,账

      linux通常重启命令?

      linux通常重启命令?,系统,工作,设备,标准,网络,命令,服务,首要,意义,参数,lin

      linux删除第一行命令?

      linux删除第一行命令?,单位,系统,命令,标的,不了,数字,连续,名称,档案,文件,m

      linux运维命令必会吗?

      linux运维命令必会吗?,工作,系统,地址,基础,网络,人员,信息,技术,软件,环境,

      linux文件io命令?

      linux文件io命令?,系统,设备,时间,地址,平均,信息,服务,工具,报告,网络,嵌入