【问题标题】:How to exit a shell script if targeted file doesn't exist?如果目标文件不存在,如何退出 shell 脚本?
【发布时间】:2013-05-30 01:43:49
【问题描述】:

鉴于下面的脚本,如果文件不存在,我想避免执行管道。

如果找不到文本文件,如何立即退出脚本?

ls */*.txt | grep ab1 | awk '{print $1, $1}' | sed "s/\"/\"\"/g" | xargs -L1 mv

【问题讨论】:

  • 您可能需要rename

标签: linux bash shell exit


【解决方案1】:

您可以通过以下方式检查文件是否存在:

if [[ -f x.txt ]] ; then
    echo file exists.
fi

如果它不退出,则退出,这样的事情就足够了:

if [[ ! -f x.txt ]] ; then
    echo 'File "x.txt" is not there, aborting.'
    exit
fi

-f <file> 只是您可以使用的众多条件表达式中的一个。如果您查看CONDITIONAL EXPRESSIONS 下的bash 手册页,您会看到一大堆。


如果(如问题更新中所述)您希望检查通配符是否导致文件,您可以简单地展开它,丢弃错误。如果没有,你最终会得到一个空字符串,可以用-z 检测到:

if [[ -z "$(ls -1 */*.txt 2>/dev/null | grep ab1)" ]] ; then
    echo 'There are no "*/*.txt" files.'
    exit
fi

请注意,我使用-1 强制每行一个文件,即使Linux ls 在输出设备不是终端(来自内存)的情况下默认执行此操作。以防万一您在在这种情况下每行强制一个的机器上尝试此操作。


但是请记住,如果您的文件名中有空格,使用ls 然后awk 来提取第 1 列不会很好。例如,文件abc ab1.txt 将导致仅提取abc 位。

使用find-print0,结合xargs-0 是正确处理可能包含“特殊”字符的文件的常用方法。您可以为find 提供许多其他选项以确保只处理所需的文件,例如-maxdepth 限制您进入目录树的深度,-name 正确过滤文件名。

但是,如果您知道您永远不会拥有这些类型的文件,那么使用ls 解决方案可能没问题,只要确保您对它的缺点感到满意。

【讨论】:

  • 嗨 paxdiablo,对不起,我错过了 * 符号,假设是 [ls * / *.txt]。
  • @amine,没有问题,添加了一个附录来解决这个问题。
  • 完美运行。谢谢帕克斯迪亚布罗。 =)
【解决方案2】:

使用test

一种快速而简短的测试存在性的方法:

test -e $FILENAME || exit

你可以这样做:

test -e $FILENAME && something | something-else 

在这种情况下,somethingsomething-else 将仅在文件存在时执行。

例如:

➤ test -e ~/.bashrc && echo True || echo False
True
➤ test -e ./exists-not && echo True || echo False
False

旁白:注意[test 的别名。 [[的语义由bash定义,可以找到on the bash manpage

然而……

...您最好使用find 来获取您的文件:

find ./ -maxdepth 2 -name "*ab1*.txt" -exec do-something-to-filename '{}' \;

由于ls 的输出无法可靠解析。如果文件名存在,这也只会执行命令do-something-to-filename,这是我认为你正在尝试做的。

{} 将替换为每次调用do-something-to-filename 的文件名。

【讨论】:

  • 嗨,brice,感谢您提供的替代方案,“test”命令既快速又简单。但是,如果不知道完整的文件名并且我只知道文件是 .txt 格式,我该怎么办。想知道测试命令是否有任何功能可以做到这一点?
  • 测试命令没有,你最好的选择肯定是使用find。您可以使用 find inside of test 将所有内容放在一行中:test -n "$(find ./ -maxdepth 2 -name "*er*.py")" && do-stuff || handle-failure
【解决方案3】:

find ... -exec ...find ... -print0 | xargs -0 ... 通常没问题,但您可以使用 bash 的 nullglob 选项直接使用 glob 进行操作:

bash-3.2$ echo *foo
*foo
bash-3.2$ shopt -s nullglob
bash-3.2$ echo *foo

bash-3.2$ 

根据脚本的其余部分,您可能希望也可能不希望使用 shopt -u nullglob 重新取消设置。

【讨论】:

    【解决方案4】:

    我试过了,这对我有用

    test -s <<your file path>> && exit 0 || <<things to do when file NOT exists>>
    

    请注意,当文件不存在时,我实际上正在退出

    【讨论】:

      猜你喜欢
      • 2021-11-15
      • 2016-06-23
      • 2020-05-31
      • 1970-01-01
      • 1970-01-01
      • 2022-01-27
      • 2014-05-29
      • 2022-11-23
      • 2014-05-19
      相关资源
      最近更新 更多