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

BH2*_*017 7 bash if-statement

我目前有这个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
Run Code Online (Sandbox Code Playgroud)

我希望这个脚本做的是将图标从我的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'
Run Code Online (Sandbox Code Playgroud)

如果你想知道为什么test -e ...在条件中它是基于关于bash脚本的教科书我一直在关注.

She*_*ish 8

检查文件和/或目录是否存在

要检查是否存在文件,请使用该-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...
Run Code Online (Sandbox Code Playgroud)

有关更多信息,请执行man test.

注意-e,此测试操作员检查文件是否存在.虽然这似乎是一个不错的选择,但-f如果文件不是常规文件,最好使用哪个将返回false./dev/null例如,文件,但也不是常规文件.在这种情况下,检查返回true是不希望的.

关于变量的说明

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

修复语法错误

您在控制语句中遇到语法错误.bash if子句的结构如下:

if ...; then
    ...
fi
Run Code Online (Sandbox Code Playgroud)

或者可选的else子句:

if ...; then
    ...
else
    ...
fi
Run Code Online (Sandbox Code Playgroud)

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

if [ ! -f "/usr/share/icons/$j/scalable" ]; then
    mkdir "/usr/share/icons/$j/scalable/"
fi
Run Code Online (Sandbox Code Playgroud)

在这里,我们添加一个感叹号(!)来翻转表达式的评估.如果表达式的计算结果为true,则前面的相同表达式!将返回false,反之亦然.


小智 5

您不能跳过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
Run Code Online (Sandbox Code Playgroud)

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

cp -a $i*.svg /usr/share/icons/$j/scalable/$i.svg
Run Code Online (Sandbox Code Playgroud)

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