【问题标题】:Bash forked for loop with while loop controlBash fork for 循环与 while 循环控制
【发布时间】:2014-08-06 08:54:30
【问题描述】:

我有一个for 循环,它将循环遍历目录中的所有文件。我想对每个文件运行一个进程(在此示例中为echo 文件名和sleep 5)。但是我希望能够一次运行这 5 个文件(在后台使用&)。问题是我不知道如何在while 循环中迭代$f,这样我就不会最终处理同一个文件五次而不是同时处理五个不同的文件。

#!/bin/bash

maxjobs=5

for f in `ls /home/user/`
do
 jobsrunning=0
  while [ $jobsrunning -lt $maxjobs ]
  do
    echo "Converting file"$f 
    sleep 5 & #wait for 5 seconds 
    jobsrunning=$((jobsrunning + 1))
    echo $jobsrunning
  done
wait
done

【问题讨论】:

  • 您永远不会将 jobsrunning 重置为 0。但是存在更好的解决方案来将文件“提供”到进程。在此处搜索find print0 xargs。不幸的是,最后一个任期可能是multiple, jobs, -n 或其他几个。
  • 不需要带有 for 的 ls ... 子shell。 “for f in /home/user/*”就足够了 - 与 ls 的不同之处在于名称将是完全限定的,因此不是直接替换。在您的情况下可能更可取,因为对这些文件的操作需要知道您当前解决方案所需的隐含“/home/user”位置
  • “这样我就不会最终处理同一个文件五次而不是同时处理五个不同的文件”没有多大意义。你为什么要处理同一个文件五次?为什么打印到屏幕时,相同的文件名会出现 5 次?
  • @Bushmills 因为 while 循环。

标签: bash for-loop while-loop


【解决方案1】:

你真的只需要重置jobsrunning,我认为你根本不需要内部循环。这只是一个条件。

#!/bin/bash

maxjobs=5
jobsrunning=0
for f in /home/user/*; do
    if (( jobsrunning >= maxjobs )); then
        wait
        jobsrunning=0
    fi
    echo "converting"
    sleep 5 & # wait for how many seconds?
    (( jobsrunning++ ))
    echo "$jobsrunning"
done
wait

也就是说,这听起来像是parallel 的工作。

【讨论】:

  • 这不太行,jobsrunning 需要在if 语句之前定义。我在尝试运行它时遇到很多错误。
  • @crysis405 好吧,明确的可能更好,但未定义的名称在 shell 算术上下文中计算为 0,所以这应该可以正常工作。但是,如果您只是在原始代码中使用[ ],那么是的,您需要定义它。不过,为什么不改用现代算术表达式呢?
  • 我在 Ubuntu 12.04 中,我似乎无法让它工作。我需要更新一些东西吗?
  • ./test_par.sh: 2: ./test_par.sh: jobsrunning: not found converting ./test_par.sh: 8: ./test_par.sh: jobsrunning++: not found test_par.sh 是我粘贴到的文件(假设是正确的)
  • @crysis405 您不能将 bash 脚本作为 sh 调用。这是两种不同的语言,这就是你遇到这个问题的原因。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-03-23
  • 1970-01-01
  • 2016-03-25
  • 2011-05-11
  • 2015-09-18
  • 1970-01-01
  • 2014-09-03
相关资源
最近更新 更多