等待在Bash中创建文件

问题描述 投票:6回答:1

我需要创建一个bash脚本来等待创建文件。该脚本将在while循环中使用sleep命令,每10秒定期检查一个文件。等待时打印留言。创建文件后显示文件的内容。以下是我试图实现的内容,但显然无效。在这一点上,我不完全确定如何继续。

#!/bin/bash
let file=$1

while '( -f !  /tmp/$1)'
do
       sleep 10
       echo "still waiting"
done

echo "Content of the file $1:"
bash unix
1个回答
12
投票

这里的问题是测试,而不是睡眠(正如假设的原始问题)。可能的最小修复可能如下所示:

while ! test -f "/tmp/$1"; do
  sleep 10
  echo "Still waiting"
done

请记住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的第一个论点,即扩展循环,是一个命令;它需要遵循与任何其他shell命令相同的语法规则。

-f作为test的参数有效 - 这个命令也可以在[的名称下访问,在该名称中使用时需要使用]作为最后一个参数 - 但它本身并不是一个有效的命令 - 当作为字符串的一部分传递,它甚至不是可以被解析为单个命令名或参数的shell字。

当您在命令内部运行'( -f ! /tmp/$1)'作为命令时,shell正在查找具有该名称的实际命令(包括空格)。您可能在PATH中没有名为'/usr/bin/( -f ! /tmp/$1)'的文件或找到该名称的任何其他命令,因此它总是会失败 - 立即退出while循环。


顺便说一句 - 如果你愿意使你的代码特定于操作系统,那么除了使用sleep等待文件存在之外,还有其他方法。例如,考虑来自inotifywait包的inotify-tools

while ! test -f "/tmp/$1"; 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

基于inotify的接口的好处是它在文件系统更改时立即返回,并且不会产生轮询开销(如果它阻止系统休眠,这可能会特别重要)。


顺便说一下,一些练习笔记:

  • 引用文件名中的扩展(即."/tmp/$1")可以防止带有空格或通配符的名称扩展为多个不同的参数。
  • >&2命令上使用echo意味着记录人类消费,使得stderr可用于程序化消费
  • let用于数学,而不是通用作业。如果你想使用"$file",没有错 - 但是赋值应该只是file=$1,没有前面的let
© www.soinside.com 2019 - 2024. All rights reserved.