34

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

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

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

4 回答 4

59

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

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>是您可以使用的众多条件表达式之一如果您查看 下的bash手册页CONDITIONAL EXPRESSIONS,您会看到一大堆。


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

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

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


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

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

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

于 2013-05-30T01:45:50.883 回答
19

利用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 定义,可以在 bash 手册页上找到

然而...

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

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

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

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

于 2013-05-30T01:48:59.980 回答
0

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.

于 2013-05-30T03:27:42.323 回答
0

我试过这个,这对我有用

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

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

于 2017-01-17T07:23:53.160 回答