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
How do I check whether a file or file directory exist in bash?
提问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 logos
directory to the scalable
theme (specified in $B
) subdirectories in /usr/share/icons
. Before it does this, however, I'd like it to create a scalable
directory 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 -f
operator. 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 -f
which will return false if the file isn't a regular file. /dev/null
for 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 if
clause is structured as following:
您在控制语句中遇到语法错误。bashif
子句的结构如下:
if ...; then
...
fi
Or optional with an else
clause:
或可选的else
子句:
if ...; then
...
else
...
fi
You cannot omit the then
clause. If you wish to only use the else
clause 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.
我在我的示例中保留了它,以防您确定它始终只有一个文件并且有意重命名它。如果不是,我建议只指定一个目标目录。