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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16826657/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 23:04:27  来源:igfitidea点击:

How to exit a shell script if targeted file doesn't exist

linuxbashshellexit

提问by amine

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 , }' | sed "s/\"/\"\"/g" | xargs -L1 mv

采纳答案by paxdiablo

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 oneof the many conditional expressions you can use. If you look at the bashman-page under CONDITIONAL EXPRESSIONS, you'll see a whole host of them.

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



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 -1to force one file per line even though Linux lsdoes 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'tforce one per line in that case.

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



Keep in mind however that, if you have spaces in your filenames, using lsand then awkto extract column 1 is not going to work too well. For example, the file abc ab1.txtwill result in the extraction of only the abcbit.

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

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

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

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

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

回答by brice

Use test

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 somethingand something-elsewill only execute if the file exists.

在这种情况下somethingsomething-else只有在文件存在时才会执行。

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

旁白:请注意,这[test. 的语义[[由 bash 定义,可以在 bash 联机帮助页上找到

However...

然而...

...you are probably better off using findto get your files:

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

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

As the output of lscan not be reliably parsed. This will also only execute the command do-something-to-filenameif 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

回答by Kevin

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

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$ 

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

根据脚本的其余部分,您可能想也可能不想用shopt -u nullglob.

回答by Kishan B

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

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