bash shell 脚本中的“期望一元运算符”

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

“unary operator expected” in shell script

bashshellunixscriptingwhile-loop

提问by iaav

I need a script to keep polling "receive_dir" directory till "stopfile" get written in the directory.

我需要一个脚本来继续轮询“receive_dir”目录,直到“stopfile”被写入目录。

This has to run despite empty directory.

尽管目录为空,但它必须运行。

So far i have this but fails if receive_dir is empty with no files with "unary operator expected". Help !!

到目前为止,我有这个,但如果 receive_dir 为空并且没有带有“一元运算符预期”的文件,则失败。帮助 !!

#!/usr/bin/ksh

until [ $i = stopfile ]
 do
   for i in `ls receive_dir`; do
   time=$(date +%m-%d-%Y-%H:%M:%S)
   echo $time
   echo $i;
  done
done

回答by Anders Martinsson

This will do what you ask for (loop until the stop file exist). I added a "sleep 1" to lower resource usage. It's also good practice to use "#!/usr/bin/env ksh" as shebang.

这将执行您的要求(循环直到停止文件存在)。我添加了“睡眠 1”以降低资源使用率。使用“#!/usr/bin/env ksh”作为shebang也是一个好习惯。

#!/usr/bin/env ksh

until [ -e receive_dir/stopfile ]
 do
   time=$(date +%m-%d-%Y-%H:%M:%S)
   echo $time
   sleep 1
done

回答by jm666

If you have empty dir, the

如果您有空目录,则

until [ $i = stopfile ]

is evaluated as

被评估为

until [ = stopfile ]

what is ofcourse syntax error.

什么是当然的语法错误。

One comment: Never parse output from ls.

一条评论:永远不要解析来自ls.

#!/bin/bash

do_something() {
    echo $(date +%m-%d-%Y-%H:%M:%S) ""
}

dir="."
until [[ -f "$dir/stopfile" ]]
do
    find "$dir" -print0 | while IFS= read -r -d '' filename
    do
        do_something "$filename"
    done
done

or (much slower)

或(慢得多)

do_something() {
    echo $(date +%m-%d-%Y-%H:%M:%S) ""
}
export -f do_something

dir="."
until [[ -f "$dir/stopfile" ]]
do
    find "$dir" -exec bash -c 'do_something "{}"' \;
done

回答by das.cyklone

You're evaluating nothing, and the 'test' isn't able to evaluate it.

您没有评估任何内容,而“测试”无法评估它。

~> [ $empty_var = stopfile ]
-bash: [: =: unary operator expected

First, don't parse ls:

首先,不要解析 ls:

http://mywiki.wooledge.org/BashPitfalls#for_i_in_.24.28ls_.2A.mp3.29

http://mywiki.wooledge.org/BashPitfalls#for_i_in_.24.28ls_.2A.mp3.29

EDIT: Part of the issue is your loop is actually doing the test, try something like this (assuming receive_dir is relative):

编辑:问题的一部分是你的循环实际上是在做测试,尝试这样的事情(假设 receive_dir 是相对的):

@user000001 is right; my original find example would suffer the same issue, so this:

@user000001 是对的;我原来的 find 例子会遇到同样的问题,所以这个:

for i in receive_dir/*
do
    time=$(date +%m-%d-%Y-%H:%M:%S)
    echo $time
    echo $i
    [ $i = stopfile ] && break
done

EDIT: Adding in another example based on your comment:

编辑:根据您的评论添加另一个示例:

How about this...

这个怎么样...

FOUND="N"
while [ "${FOUND}" = "N" ]
do
    for i in receive_dir/*
    do
        time=$(date +%m-%d-%Y-%H:%M:%S)
        echo $time
        echo $i
        [ "$i" = stopfile ] && FOUND="Y"
    done
sleep 60 
done

回答by user000001

Another option is to use inotifywaitto monitor the status of the directory. For example, this script will run the loop until the file "stopfile" is touched.

另一种选择是用来inotifywait监视目录的状态。例如,此脚本将运行循环,直到触及文件“stopfile”。

until inotifywait "receive_dir" | grep "stopfile"
do 
    echo "running" 
done
echo "done"

The advantage is that these is no busy loop, and that you don't have to repeatedly call the (potentially expensive) find command

优点是这些不是忙循环,并且您不必重复调用(可能很昂贵) find 命令