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脚本。现在的孩子们都是这样成长的:他们的目录名中可以有空格和许多其他有趣的字符。(空间!在我的时代,我们没有美好的空间!;)
有一天,其中一个孩子会运行你的脚本,把
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条件表达式和
我发现
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 |
您可以使用
-d file True if file exists and is a directory.
例如:
1 | test -d"/etc" && echo Exists || echo Does not exist |
注:
[ - This is a synonym for thetest builtin, but the last argument must, be a literal] , to match the opening[ .
有关可能的选项或进一步的帮助,请检查:
help [ help test man test 或man [ 。
测试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",否则返回非零值。假设
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 } |
这种方法的好处在于,我不必考虑好的错误消息。
接下来是我们传给
tl;dr:如果传递给这个函数的字符串是空的,那么我们再次从子shell
引用
1 | ${parameter:?word} |
If
parameter is set and is non-null then substitute its value;
otherwise, printword and exit from the shell (if not interactive).
Ifword 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文档特有的,如
在这种特定的情况下,我知道标准的错误消息
哲学注释:shell不是面向对象的语言,因此消息称为
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 |
更多使用
检查子目录中是否存在文件夹:
1
2
3
4
5
6found=`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
5found=`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
5found=`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 |
只要使用
注意,
你有没有考虑过在江户中做任何你想做的事情,而不是在你跳之前看?
也就是说,如果您想在输入目录之前检查它是否存在,请尝试这样做:
1 2 3 4 | if pushd /path/you/want/to/enter; then # commands you want to run in this directory popd fi |
如果您给
似乎比这更好,这需要重复你自己:
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 |
同样的事情也适用于
要检查多个目录,请使用以下代码:
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"; |
使用
1 2 3 4 | if [ -e ${FILE_PATH_AND_NAME} ] then echo"The file or directory exists." fi |
根据乔纳森评论:
如果您想创建目录,但它还不存在,那么最简单的方法是使用创建目录的
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 |
只有一行中的以下命令将告诉您给定的
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" |
如果发现上述方法之一存在问题。
使用
$[[
如果要检查目录是否存在,无论它是真正的目录还是符号链接,请使用以下命令:
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
检查不存在的文件:
输出:
正在检查现有目录:
输出:
以三元形式,
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 |