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

时间:2015-06-23 00:40:47

标签: 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

我希望此脚本执行的操作是将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'

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

2 个答案:

答案 0 :(得分:7)

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

要检查中是否存在文件,请使用-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...

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

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

关于变量的说明

一定要引用变量,一旦变量中包含空格或任何其他特殊字符,就会产生不良副作用。因此,当您测试文件和目录是否存在时,请将文件/目录用双引号括起来。如果[ -f "/path/to/some/${dir}/" ] dir中有空格,则[ -f /path/to/some/${dir}/ ]之类的内容会有效,而以下内容会失败。

修复语法错误

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

if ...; then
    ...
fi

或者else子句可选:

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

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

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

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

答案 1 :(得分:4)

您无法跳过 if 语句的然后部分,最简单的解决方案就是取消测试

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

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

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

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