如果目标文件不存在,如何退出shell脚本

时间:2022-03-30 23:45:16

Given the script below, I would like to avoid the execution of the pipeline if a file does not exist.

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

How may I exit the script straight away if the txt file is not found?

如果找不到txt文件,我怎么能立即退出脚本?

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

4 个解决方案

#1


34  

You can check for file existence with something like:

您可以使用以下内容检查文件是否存在:

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

To exit if it doesn't, something like this would suffice:

要退出,如果没有,这样的东西就足够了:

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

The -f <file> is only one of the many conditional expressions you can use. If you look at the bash man-page under CONDITIONAL EXPRESSIONS, you'll see a whole host of them.

-f 只是您可以使用的众多条件表达式之一。如果你看一下CONDITIONAL EXPRESSIONS下的bash man-page,你会看到它们中的一大部分。


If (as stated in a question update) you wish to check if a wildcard results in files, you can simply expand it, throwing away the errors. If there are none, you'll end up with an empty string which can be detected with -z:

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

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

Note that I've used -1 to force one file per line even though Linux ls does that by default if the output device is not a terminal (from memory). That's just in case you try this on a machine that doesn't force one per line in that case.

请注意,我已经使用-1强制每行强制一个文件,即使Linux ls默认情况下输出设备不是终端(来自内存)也是如此。这是为了防止你在一台机器上尝试这种情况,在这种情况下不会强制每行一个。


Keep in mind however that, if you have spaces in your filenames, using ls and then awk to extract column 1 is not going to work too well. For example, the file abc ab1.txt will result in the extraction of only the abc bit.

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

Using find with -print0, combined with xargs with -0 is the usual way to properly process files which may have "special" characters in them. There are many other options you can give to find to ensure only the files required are processed, such as -maxdepth to limit how far down the directory tree you go, and -name to properly filter file names.

将find与-print0一起使用,将xargs与-0结合使用是正确处理可能包含“特殊”字符的文件的常用方法。您可以提供许多其他选项以确保只处理所需的文件,例如-maxdepth用于限制目标树的下移,以及-name以正确过滤文件名。

However, if you know that you will never have these types of files, it's probably okay to use the ls solution, just make sure you're comfortable with its shortcomings.

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

#2


8  

Use test

A quick and short way of testing for existence:

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

test -e $FILENAME || exit

You can chain it by doing:

你可以通过这样做来链接它:

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

In which case something and something-else will only execute if the file exists.

在这种情况下,只有在文件存在的情况下才会执行某些事情。

For example:

例如:

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

Aside: Note that [ is an alias for test. The semantics of [[ are defined by bash and can be found on the bash manpage

旁白:请注意[是测试的别名。 [[由bash定义,可以在bash联机帮助页上找到)的语义

However...

...you are probably better off using find to get your files:

...你可能最好用find来获取你的文件:

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

As the output of ls can not be reliably parsed. This will also only execute the command do-something-to-filename if the filename exist, which is what I think you are trying to do.

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

{} will be replaced by the filename for each invocation of do-something-to-filename.

每次调用do-something-to-filename都将替换为{}。

#3


0  

find ... -exec ... or find ... -print0 | xargs -0 ... is generally fine, but you can do it directly with a glob using bash's nullglob option:

找到... -exec ...或找到... -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$ 

Depending on the rest of your script, you may or may not want to re-unset that with shopt -u nullglob.

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

#4


0  

I tried this and this worked for me

我试过这个,这对我有用

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

Note that i am actually exiting when the file is not present

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

#1


34  

You can check for file existence with something like:

您可以使用以下内容检查文件是否存在:

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

To exit if it doesn't, something like this would suffice:

要退出,如果没有,这样的东西就足够了:

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

The -f <file> is only one of the many conditional expressions you can use. If you look at the bash man-page under CONDITIONAL EXPRESSIONS, you'll see a whole host of them.

-f 只是您可以使用的众多条件表达式之一。如果你看一下CONDITIONAL EXPRESSIONS下的bash man-page,你会看到它们中的一大部分。


If (as stated in a question update) you wish to check if a wildcard results in files, you can simply expand it, throwing away the errors. If there are none, you'll end up with an empty string which can be detected with -z:

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

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

Note that I've used -1 to force one file per line even though Linux ls does that by default if the output device is not a terminal (from memory). That's just in case you try this on a machine that doesn't force one per line in that case.

请注意,我已经使用-1强制每行强制一个文件,即使Linux ls默认情况下输出设备不是终端(来自内存)也是如此。这是为了防止你在一台机器上尝试这种情况,在这种情况下不会强制每行一个。


Keep in mind however that, if you have spaces in your filenames, using ls and then awk to extract column 1 is not going to work too well. For example, the file abc ab1.txt will result in the extraction of only the abc bit.

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

Using find with -print0, combined with xargs with -0 is the usual way to properly process files which may have "special" characters in them. There are many other options you can give to find to ensure only the files required are processed, such as -maxdepth to limit how far down the directory tree you go, and -name to properly filter file names.

将find与-print0一起使用,将xargs与-0结合使用是正确处理可能包含“特殊”字符的文件的常用方法。您可以提供许多其他选项以确保只处理所需的文件,例如-maxdepth用于限制目标树的下移,以及-name以正确过滤文件名。

However, if you know that you will never have these types of files, it's probably okay to use the ls solution, just make sure you're comfortable with its shortcomings.

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

#2


8  

Use test

A quick and short way of testing for existence:

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

test -e $FILENAME || exit

You can chain it by doing:

你可以通过这样做来链接它:

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

In which case something and something-else will only execute if the file exists.

在这种情况下,只有在文件存在的情况下才会执行某些事情。

For example:

例如:

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

Aside: Note that [ is an alias for test. The semantics of [[ are defined by bash and can be found on the bash manpage

旁白:请注意[是测试的别名。 [[由bash定义,可以在bash联机帮助页上找到)的语义

However...

...you are probably better off using find to get your files:

...你可能最好用find来获取你的文件:

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

As the output of ls can not be reliably parsed. This will also only execute the command do-something-to-filename if the filename exist, which is what I think you are trying to do.

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

{} will be replaced by the filename for each invocation of do-something-to-filename.

每次调用do-something-to-filename都将替换为{}。

#3


0  

find ... -exec ... or find ... -print0 | xargs -0 ... is generally fine, but you can do it directly with a glob using bash's nullglob option:

找到... -exec ...或找到... -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$ 

Depending on the rest of your script, you may or may not want to re-unset that with shopt -u nullglob.

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

#4


0  

I tried this and this worked for me

我试过这个,这对我有用

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

Note that i am actually exiting when the file is not present

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