【问题标题】:How do I check whether a file or file directory exist in bash?如何检查bash中是否存在文件或文件目录?
【发布时间】:2015-06-23 00:40:47
【问题描述】:

我目前有这个 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 目录复制到/usr/share/icons 中的scalable 主题(在$B 中指定)子目录。但是,在它执行此操作之前,我希望它在这些主题子目录中创建一个 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 脚本的教科书。

【问题讨论】:

    标签: bash if-statement


    【解决方案1】:

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

    要检查 中是否存在文件,请使用-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,反之亦然。

    【讨论】:

    • 将 test -e ... 更改为 test [-d ...] 给出:./copyicon.sh: 第 8 行:在意外标记 else' ./copyicon.sh: line 8: 附近出现语法错误 if test [ -d /usr/share/icons/$j/可扩展];否则'
    • 那是因为你的语法错误。我会更新答案。
    • “否定条件”是指感叹号 (!) 如果目录不存在则返回 true,如果存在则返回 false?
    • 没错!感叹号将 true 转换为 false,反之亦然。 - 所以如果表达式为假,带有! 的相同表达式将返回真,反之亦然!
    【解决方案2】:

    您不能跳过 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
    

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

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

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

    【讨论】:

    • 这很棒。对我来说,适用于两个目录或文件。 :)
    猜你喜欢
    • 2013-04-24
    • 1970-01-01
    • 2012-05-17
    • 1970-01-01
    • 2018-05-13
    • 2019-09-29
    • 2019-11-01
    • 2013-04-07
    • 2015-07-07
    相关资源
    最近更新 更多