等待在 Bash 中创建文件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/40047801/
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
Waiting for a file to be created in Bash
提问by J.Clark
I need to create a bash script to wait for a file to be created. The script will use sleep command inside a while loop to periodically check on a file every 10 seconds. Print out a message while waiting. Display the content of the file once the file is created. Below is what I have tried to implement and it obviously does not work. At this point, I'm not entirely sure how to proceed.
我需要创建一个 bash 脚本来等待创建文件。该脚本将在 while 循环中使用 sleep 命令每隔 10 秒定期检查文件。等待时打印一条消息。创建文件后显示文件的内容。以下是我尝试实施的内容,但显然行不通。在这一点上,我不完全确定如何进行。
#!/bin/bash
let file=
while '( -f ! /tmp/)'
do
sleep 10
echo "still waiting"
done
echo "Content of the file :"
回答by Charles Duffy
The problem here is with the test, not the sleep (as the original question hypothesized). The smallest possible fix might look as follows:
这里的问题在于测试,而不是睡眠(正如最初的问题假设的那样)。最小的修复可能如下所示:
while ! test -f "/tmp/"; do
sleep 10
echo "Still waiting"
done
Keep in mind the syntax for a while
loop:
请记住while
循环的语法:
while: while COMMANDS; do COMMANDS; done Expand and execute COMMANDS as long as the final command in the `while' COMMANDS has an exit status of zero.
while: while COMMANDS; do COMMANDS; done Expand and execute COMMANDS as long as the final command in the `while' COMMANDS has an exit status of zero.
That is to say, the first argument given to while
, expanding the loop, is a command; it needs to follow the same syntax rules as any other shell command.
也就是说,给 的第一个参数while
,展开循环,是一个命令;它需要遵循与任何其他 shell 命令相同的语法规则。
-f
is valid as an argument to test
-- a command which is also accessible under the name [
, requiring a ]
as the last argument when used in that name -- but it's not valid as a command in and of itself -- and when passed as part of a string, it's not even a shell word that couldbe parsed as an individual command name or argument.
-f
作为参数有效test
- 也可以在 name 下访问的命令,在该名称中使用[
时需要 a]
作为最后一个参数 - 但它本身作为命令无效 - 当作为的一部分传递时一个字符串,它甚至不是一个shell词,可以被解析为一个单独的命令名称或参数。
When you run '( -f ! /tmp/$1)'
as a command, inside quotes, the shell is looking for an actual command with exactly that name (including spaces). You probably don't have a file named '/usr/bin/( -f ! /tmp/$1)'
in your PATH or any other command by that name found, so it'll always fail -- exiting the while
loop immediately.
当您'( -f ! /tmp/$1)'
作为命令运行时,在引号内,shell 正在寻找具有该名称(包括空格)的实际命令。您可能没有'/usr/bin/( -f ! /tmp/$1)'
在您的 PATH 中命名的文件或任何其他以该名称命名的命令,因此它总是会失败——while
立即退出循环。
By the way -- if you're willing to make your code OS-specific, there are approaches other than using sleep
to wait for a file to exist. Consider, for instance, inotifywait
, from the inotify-tools
package:
顺便说一句——如果你愿意让你的代码特定于操作系统,除了sleep
用来等待文件存在之外,还有其他方法。例如inotifywait
,从inotify-tools
包中考虑:
while ! test -f "/tmp/"; do
echo "waiting for a change to the contents of /tmp" >&2
inotifywait --timeout 10 --event create /tmp >/dev/null || {
(( $? == 2 )) && continue ## inotify exit status 2 means timeout expired
echo "unable to sleep with inotifywait; doing unconditional 10-second loop" >&2
sleep 10
}
done
The benefit of an inotify-based interface is that it returns immediately upon a filesystem change, and doesn't incur polling overhead (which can be particularly significant if it prevents a system from sleeping).
基于 inotify 的接口的好处是它在文件系统更改时立即返回,并且不会产生轮询开销(如果它阻止系统休眠,这可能特别重要)。
By the way, some practice notes:
顺便说一下,一些练习笔记:
- Quoting expansions in filenames (ie.
"/tmp/$1"
) prevents names with spaces or wildcards from being expanded into multiple distinct arguments. - Using
>&2
onecho
commands meant to log for human consumption keeps stderr available for programmatic consumption let
is used for math, not general-purpose assignments. If you want to use"$file"
, nothing wrong with that -- but the assignment should just befile=$1
, with no precedinglet
.
- 在文件名中引用扩展(即
"/tmp/$1"
)可防止带有空格或通配符的名称被扩展为多个不同的参数。 - 使用
>&2
上echo
意味着日志供人食用的命令保持标准错误可以编程消费 let
用于数学,而不是通用任务。如果你想使用"$file"
,那没有错——但赋值应该是file=$1
,没有前面的let
。