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

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

要检查一个目录是否存在于一个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所指出的(感谢Jon),如果您不考虑链接到目录的符号链接也会通过此检查,那么后续命令可能无法正常工作。 例如运行这个:

 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 

特别要注意用于包裹variables的双引号,其原因可以由8jean 在另一个答案中解释。

如果variables包含空格或其他不寻常的字符,可能会导致脚本失败。

请记住,在bash脚本中引用variables时总是用双引号包装variables。 现在的孩子长大了,他们的目录名中可以有空格和许多其他有趣的字符。 (空间!在我的日子里,我们没有任何花哨的空间!))

有一天,其中一个孩子会用$DIRECTORY设置为"My M0viez"来运行你的脚本,你的脚本将会炸毁。 你不要那个。 所以使用这个。

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

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

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

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

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

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

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

您可以在Bash条件expression式的Bash手册和[内build命令和[[复合 命令]中find更多信息。

更短的forms:

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

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

 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 

注意 :请小心,在开启和closures支撑两侧留出空的空间。

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

 -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 

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

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

例如:

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

注: test命令与条件expression式[ (请参阅: man [ )相同,因此它可以在各个shell脚本之间移植。

[ – 这是内buildtest的同义词,但最后一个参数必须是文字] ,以匹配开放[

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

  • help [
  • help test
  • man testman [
 if [ -d "$DIRECTORY" ]; then # Here if $DIRECTORY exists fi 

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

 [ -d . ] || echo "No" 

这是一个非常实用的习惯用法:

 (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} 。 这是更详细的参数replaceforms,下面将对此进行更详细的说明。

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


ksh93手册页引用:

 ${parameter:?word} 

如果parameter设置为非null,则replace其值; 否则,打印word并从shell中退出(如果不是交互的话)。 如果word被省略,则打印标准消息。

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

这里的措辞是shell文档特有的,因为word可以指任何合理的string,包括空格。

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

一个philosphical注意:shell不是一个面向对象的语言,所以消息说pathname ,而不是directory 。 在这个层面上,我宁愿保持简单 – 函数的参数只是string。

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

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

在bash promt上键入这个代码

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

其实,你应该使用几个工具来获得防弹的方法:

 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),所带来的好处比麻烦。

使用find更多function

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

     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 

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

 if [ -d "$DIRECTORY1" ] && [ -d "$DIRECTORY2" ] then # Things to do fi 
 [ -d ~/Desktop/TEMPORAL/ ] && echo "DIRECTORY EXISTS" || echo "DIRECTORY DOES NOT EXIST" 
 [[ -d "$DIR" && ! -L "$DIR" ]] && echo "It's a directory and not a symbolic link" 

注意:引用variables是一个好习惯。

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

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

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

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

这个答案被封装成一个shell脚本

例子

 $ 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 

is_dir

 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"; 

按照Jonathan的评论:

如果你想创build目录并且目录还不存在,那么最简单的方法就是使用mkdir -p来创build目录 – 以及path上的任何缺less的目录 – 如果目录已经存在,则不会失败,所以你可以一次完成:

 mkdir -p /some/directory/you/want/to/exist || exit 1 
 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 

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

下面的命令在一行中会告诉你给定的ISDIRvariables是否包含一个目录的path:

 [[ $(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 

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

 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 

只有在执行的时候,你才能成功执行你正在一个目录中,你有一个子目录,你碰巧检查。

我理解了这样的初始问题:validation目录是否存在,而不pipe用户在文件系统中的位置。 所以使用命令“查找”可能会有诀窍:

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

这个解决scheme是好的,因为它允许使用通配符,这是search文件/目录时的一个有用的function。 唯一的问题是,如果search到的目录不存在,那么'find'命令将不会输出stdout(我的口味不是一个优雅的解决scheme),并且会有一个零退出。 也许有人可以改善这一点。

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

如果你想检查一个目录是否存在,不pipe它是一个真实的目录还是一个符号链接,使用这个:

 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”后直接检查返回码。

(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 ls -ld SAMPLE_DIR| grep ^d | wc -l ls -ld SAMPLE_DIR| grep ^d | wc -l -eq 1]] && echo exists || 不存在-ksh:不:没有find[没有这样的文件或目录]

下面find可以用,

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

从脚本文件myScript.sh:

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

要么

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

Git Bash + Dropbox + Windows:

没有其他解决scheme为我的Dropbox文件夹工作,这是奇怪的,因为我可以推入Dropbox的符号path。

 #!/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