bash 如何检查文件或文件目录是否存在于bash中?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/30992072/
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-18 13:14:57  来源:igfitidea点击:

How do I check whether a file or file directory exist in bash?

bashif-statement

提问by BH2017

I currently have this bash script (which is located in my home directory, i.e., /home/fusion809/and I am running it as root as it's necessary for the icon copying lines):

我目前有这个 bash 脚本(它位于我的主目录中,即,/home/fusion809/我以 root 身份运行它,因为它是图标复制行所必需的):

cd /home/fusion809/Pictures/Icon*

declare -a A={Arch,Debian,Fedora,Mageia,Manjaro,OpenSUSE}
declare -a B={Adwaita,Faenza,gnome,Humanity}

for i in $A; do
  for j in $B; do
    if test -e /usr/share/icons/$j/scalable ; else
        mkdir /usr/share/icons/$j/scalable/
    fi
    if test -e /usr/share/icons/$j/scalable/$i.svg ; else
      cp -a $i*.svg /usr/share/icons/$j/scalable/$i.svg
    fi
  done
done

What I want this script to do is to copy icons from my Pictures/Icons and logosdirectory to the scalabletheme (specified in $B) subdirectories in /usr/share/icons. Before it does this, however, I'd like it to create a scalabledirectory in these theme subdirectories if it does not already exist. The problem is that the else part of the conditionals is not being read properly, as I keep receiving this error:

我想这个脚本做的是从我的复制图标Pictures/Icons and logos目录的scalable主题(在指定$B)的子目录/usr/share/icons。但是,在执行此操作之前,我希望它scalable在这些主题子目录中创建一个目录(如果该目录尚不存在)。问题是条件的 else 部分没有被正确读取,因为我一直收到这个错误:

./copyicon.sh: line 8: syntax error near unexpected token `else'
./copyicon.sh: line 8: `    if test -e /usr/share/icons/$j/scalable ; else'

If you're wondering why the test -e ...in the conditional it's based on a textbook on bash scripting I've been following.

如果您想知道为什么test -e ...在有条件的情况下它基于我一直在关注的有关 bash 脚本编写的教科书。

回答by ShellFish

Checking file and/or directory existence

检查文件和/或目录存在

To check whether a file exists in bash, you use the -foperator. For directories, use -d. Example usage:

要检查文件是否存在于bash 中,请使用-f运算符。对于目录,使用-d. 用法示例:

$ mkdir dir
$ [ -d dir ] && echo exists!
exists!
$ rmdir dir
$ [ -d dir ] && echo exists!
$ touch file
$ [ -f file ] || echo "doesn't exist..."
$ rm file
$ [ -f file ] || echo "doesn't exist..."
doesn't exist...

For more information simply execute man test.

有关更多信息,只需执行man test

A note on -e, this test operator checks whether a file exists. While this may seem like a good choice, it's better to use -fwhich will return false if the file isn't a regular file. /dev/nullfor example is a file but nor a regular file. Having the check return true is undesired in this case.

请注意-e,此测试运算符会检查文件是否存在。虽然这似乎是一个不错的选择,但-f如果文件不是常规文件,最好使用which 将返回 false。/dev/null例如是一个文件,但也不是一个普通文件。在这种情况下,不希望检查返回 true。

A note on variables

关于变量的注释

Be sure to quote variables too, once you have a space or any other special character contained in a variable it can have undesired side effects. So when you test for existence of files and directories, wrap the file/dir in double quotes. Something like [ -f "/path/to/some/${dir}/" ]will work while the following would fail if there is a space in dir: [ -f /path/to/some/${dir}/ ].

一定要引用变量,一旦变量中包含空格或任何其他特殊字符,它可能会产生不良副作用。因此,当您测试文件和目录是否存在时,请将文件/目录用双引号括起来。喜欢的东西[ -f "/path/to/some/${dir}/" ]会工作,而如果有一个空间,在下面会失败dir[ -f /path/to/some/${dir}/ ]

Fixing the syntax error

修复语法错误

You are experiencing a syntax error in the control statements. A bash ifclause is structured as following:

您在控制语句中遇到语法错误。bashif子句的结构如下:

if ...; then
    ...
fi

Or optional with an elseclause:

或可选的else子句:

if ...; then
    ...
else
    ...
fi

You cannot omit the thenclause. If you wish to only use the elseclause you should negate the condition. Resulting in following code:

您不能省略该then子句。如果你只想使用else子句,你应该否定条件。导致以下代码:

if [ ! -f "/usr/share/icons/$j/scalable" ]; then
    mkdir "/usr/share/icons/$j/scalable/"
fi

Here we add an exclamation point (!) to flip the expression's evaluation. If the expression evaluates to true, the same expression preceded by !will return false and the other way around.

这里我们添加一个感叹号 ( !) 来翻转表达式的计算。如果表达式的计算结果为真,前面的相同表达式!将返回假,反之亦然。

回答by RSchulze

You can't skip the thenpart of the ifstatement, easiest solution would be to just negate the test

您不能跳过if语句的then部分,最简单的解决方案是否定测试

if [[ ! -e /usr/share/icons/${j}/scalable ]] ; then
    mkdir /usr/share/icons/${j}/scalable/
fi
if [[ ! -e /usr/share/icons/${j}/scalable/${i}.svg ]] ; then
  cp -a ${i}*.svg /usr/share/icons/${j}/scalable/${i}.svg
fi

I left it with -e (exists), but you might consider using -d for directories or -f for files and some error handling to catch stuff (e.g. /usr/share/icons/$j/scalable/exists, but is a file and not a directory for whatever reason.) I also noticed that in your original code you are potentially trying to copy multiple files into one:

我把它留给了 -e(存在),但你可能会考虑对目录使用 -d 或对文件使用 -f 和一些错误处理来捕捉东西(例如/usr/share/icons/$j/scalable/存在,但是是一个无论出于何种原因,文件而不是目录。)我还注意到,在您的原始代码中,您可能试图将多个文件复制到一个文件中:

cp -a $i*.svg /usr/share/icons/$j/scalable/$i.svg

I left it that way in my example in case you are sure that it is always only one file and are intentionally renaming it. If not I'd suggest only specifying a target directory.

我在我的示例中保留了它,以防您确定它始终只有一个文件并且有意重命名它。如果不是,我建议只指定一个目标目录。