【问题标题】:“unary operator expected” in shell scriptshell脚本中的“一元运算符预期”
【发布时间】:2013-07-16 11:04:13
【问题描述】:

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

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

到目前为止,我有这个但如果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

【问题讨论】:

标签: bash shell unix scripting while-loop


【解决方案1】:

您什么都不评估,而“测试”无法评估它。

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

首先,不要解析 ls:

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

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

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

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

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

这个怎么样...

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

【讨论】:

  • 确实,我同意。我承认我宁愿使用[[ $i == stopfile ]] 来处理它,以防止命令替换引起的问题,但他使用的是 ksh,我认为它无法使用[[ ]] 语法。
  • [[ ]] 是 bash 和 ksh 中的内置函数。
  • 我还需要在receive_dir中回显文件并让循环运行直到stopfile在目录中移动。
  • 这个怎么样(为了可读性也添加到原始帖子中):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 done
【解决方案2】:

这将按照您的要求执行(循环直到停止文件存在)。我添加了“睡眠 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

【讨论】:

    【解决方案3】:

    如果你有空目录,

    until [ $i = stopfile ]
    

    被评估为

    until [ = stopfile ]
    

    什么是语法错误。

    一条评论:永远不要解析来自ls 的输出。

    #!/bin/bash
    
    do_something() {
        echo $(date +%m-%d-%Y-%H:%M:%S) "$1"
    }
    
    dir="."
    until [[ -f "$dir/stopfile" ]]
    do
        find "$dir" -print0 | while IFS= read -r -d '' filename
        do
            do_something "$filename"
        done
    done
    

    或(慢得多)

    do_something() {
        echo $(date +%m-%d-%Y-%H:%M:%S) "$1"
    }
    export -f do_something
    
    dir="."
    until [[ -f "$dir/stopfile" ]]
    do
        find "$dir" -exec bash -c 'do_something "{}"' \;
    done
    

    【讨论】:

    • 我还需要在receive_dir中回显文件。
    • @iaav 不明白。 do_someting 打印日期和文件名。如果您需要在单独的行中,只需添加另一个 echo...
    • @iaav 也许 - 不知道 ksh - 使用 bash。你的问题被标记为 bash。
    【解决方案4】:

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

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

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

    【讨论】:

      猜你喜欢
      • 2018-10-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-01-20
      • 2010-09-05
      相关资源
      最近更新 更多