While 循环以测试文件是否存在于 bash 中

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2379829/
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-09-09 19:00:18  来源:igfitidea点击:

While loop to test if a file exists in bash

bashshell

提问by Zenet

I'm working on a shell script that does certain changes on a txt file only if it does exist, however this test loop doesn't work, I wonder why? Thank you!

我正在处理一个 shell 脚本,它只在 txt 文件存在时才对它进行某些更改,但是这个测试循环不起作用,我想知道为什么?谢谢!

while [ ! -f /tmp/list.txt ] ;
do
      sleep 2
done

回答by CWF

When you say "doesn't work", how do you know it doesn't work?

当您说“不起作用”时,您怎么知道它不起作用?

You might try to figure out if the file actually exists by adding:

您可能会尝试通过添加以下内容来确定该文件是否确实存在:

while [ ! -f /tmp/list.txt ]
do
  sleep 2 # or less like 0.2
done
ls -l /tmp/list.txt

You might also make sure that you're using a Bash (or related) shell by typing 'echo $SHELL'. I think that CSH and TCSH use a slightly different semantic for this loop.

您还可以通过键入“echo $SHELL”来确保您使用的是 Bash(或相关)shell。我认为 CSH 和 TCSH 对这个循环使用了稍微不同的语义。

回答by yingted

If you are on linux and have inotify-tools installed, you can do this:

如果您使用的是 linux 并安装了 inotify-tools,您可以这样做:

file=/tmp/list.txt
while [ ! -f "$file" ]
do
    inotifywait -qqt 2 -e create -e moved_to "$(dirname $file)"
done

This reduces the delay introduced by sleep while still polling every "x" seconds. You can add more events if you anticipate that they are needed.

这减少了睡眠引入的延迟,同时仍然每“x”秒轮询一次。如果您预计需要它们,您可以添加更多事件。

回答by David Cox

I had the same problem, put the ! outside the brackets;

我有同样的问题,把!括号外;

while ! [ -f /tmp/list.txt ];
do
    echo "#"
    sleep 1
done

Also, if you add an echo inside the loop it will tell you if you are getting into the loop or not.

此外,如果您在循环内添加回声,它会告诉您是否进入循环。

回答by Zane Hooper

I ran into a similar issue and it lead me here so I just wanted to leave my solution for anyone who experiences the same.

我遇到了一个类似的问题,它把我带到了这里,所以我只想把我的解决方案留给有同样经历的人。

I found that if I ran cat /tmp/list.txtthe file would be empty, even though I was certain that there were contents being placed immediately in the file. Turns out if I put a sleep 1;just before the cat /tmp/list.txtit worked as expected. There must have been a delay between the time the file was created and the time it was written, or something along those lines.

我发现如果我运行cat /tmp/list.txt该文件将是空的,即使我确定有内容立即放入文件中。事实证明,如果我sleep 1;cat /tmp/list.txt它按预期工作之前放了一个。在创建文件和写入文件之间一定存在延迟,或者类似的事情。

My final code:

我的最终代码:

while [ ! -f /tmp/list.txt ];
do
    sleep 1;
done;
sleep 1;
cat /tmp/list.txt;

Hope this helps save someone a frustrating half hour!

希望这有助于节省某人令人沮丧的半小时!

回答by Ruslan Shaydulin

Like @zane-hooper, I've had a similar problem on NFS. On parallel / distributed filesystems the lag between you creating a file on one machine and the other machine "seeing" it can be very large, so I could wait up to a full minute after the creation of the file before the while loop exits (and there also is an aftereffect of it "seeing" an already deleted file).

和@zane-hooper 一样,我在 NFS 上也遇到过类似的问题。在并行/分布式文件系统上,在一台机器上创建文件和另一台机器“看到”它之间的延迟可能非常大,所以我可以在创建文件后等待一整分钟,然后才退出 while 循环(和还有一个后遗症是它“看到”了一个已经删除的文件)。

This creates the illusion that the script "doesn't work", while in fact it is the filesystem that is dropping the ball.

会造成脚本“不起作用”的错觉,而实际上是文件系统在丢球。

This took me a while to figure out, hope it saves somebody some time.

这花了我一段时间才弄明白,希望它可以节省一些时间。

PS This also causes an annoying number of "Stale file handler" errors.

PS 这也会导致许多烦人的“陈旧文件处理程序”错误。

回答by neerajmalve

works with bash and sh both:

适用于 bash 和 sh 两者:

touch /tmp/testfile
sleep 10 && rm /tmp/testfile &
until ! [ -f /tmp/testfile ]
do
   echo "testfile still exist..."
   sleep 1
done
echo "now testfile is deleted.."

回答by ZedTuX

Here is a version with a timeoutso that after an amount of time the loop ends with an error:

这是一个带有超时的版本,以便在一段时间后循环以错误结束:

# After 60 seconds the loop will exit
timeout=60

while [ ! -f /tmp/list.txt ];
do
  # When the timeout is equal to zero, show an error and leave the loop.
  if [ "$timeout" == 0 ]; then
    echo "ERROR: Timeout while waiting for the file /tmp/list.txt."
    exit 1
  fi

  sleep 1

  # Decrease the timeout of one
  ((timeout--))
done

回答by ghostdog74

do it like this

像这样做

while true
do
  [ -f /tmp/list.txt ] && break
  sleep 2
done
ls -l /tmp/list.txt