【问题标题】:How to loop an executable command in the terminal in Linux?如何在 Linux 的终端中循环执行可执行命令?
【发布时间】:2012-06-12 22:25:28
【问题描述】:

首先让我描述一下我的情况,我在 Linux 平台上工作,并且有一组 .bmp 文件,这些文件将图片编号从 filename0022.bmp 增加到 filename0680.bmp。所以一共有658张图片。我希望能够通过对图片进行操作的 .exe 文件运行这些图片中的每一个,然后将文件踢出到用户指定的文件中,它还有一些阈值参数:lower、upper。所以可执行文件的典型调用是:

./filter inputfile outputfile lower upper

有没有一种方法可以让我仅从终端或通过创建某种 bash 脚本来循环调用所有文件?我的问题与此类似:Execute a command over multiple files with a batch file 但这次我在 Linux 命令行终端中工作。

【问题讨论】:

    标签: linux loops file-io


    【解决方案1】:

    您可能有兴趣研究 bash 脚本。

    您可以直接在 shell 中执行 for 循环中的命令。

    一个简单的循环来生成您特别提到的数字。例如,从外壳:

    user@machine $ for i in {22..680} ; do
    > echo "filename${i}.bmp"
    > done
    

    这将为您提供从filename22.bmpfilename680.bmp 的列表。这只是处理您提到的范围的迭代。这不包括零填充数字。为此,您可以使用printfprintf 语法是 printf format argument。我们可以使用前面循环中的$i 变量作为参数,并应用%Wd 格式,其中W 是宽度。前缀 W 占位符将指定要使用的字符。示例:

    user@machine $ for i in {22..680} ; do
    > echo "filename$(printf '%04d' $i).bmp"
    > done
    

    在上面$()充当一个变量,执行命令获取与预定义值相反的值。

    现在应该会为您提供您指定的文件名。我们可以把它应用到实际应用中:

    user@machine $ for i in {22..680} ; do
    > ./filter "filename$(printf '%04d' $i).bmp" lower upper
    > done
    

    这可以改写成一行:

    user@machine $ for i in {22..680} ; do ./filter "filename$(printf '%04d' $i).bmp" lower upper ; done
    

    问题中需要注意的一点,.exe 文件通常以COFF 格式编译,而 linux 需要ELF 格式的可执行文件。

    【讨论】:

    • user@machine $ 是模拟一个shell提示符,> 是模拟提示符继续,在完成命令执行之前期待更多。
    【解决方案2】:

    这是一个简单的例子:

    for i in {1..100}; do echo "Hello Linux Terminal"; done
    

    追加到文件:(>>用来追加,也可以用>覆盖)

    for i in {1..100}; do echo "Hello Linux Terminal" >> file.txt; done
    

    【讨论】:

      【解决方案3】:

      你可以试试这样的……

      #! /bin/bash
      for ((a=022; a <= 658 ; a++))
      do
         printf "./filter filename%04d.bmp outputfile lower upper" $a | "sh"
      done
      

      【讨论】:

      • 这是我尝试过的,它在我的屏幕上打印了一堆有点相关的东西,但实际上并没有创建任何文件...#! /bin/bash for ((a=022; a
      • 尝试将其制作成一个 .sh 文件(使用我上面添加的新内容),然后通过在同一目录中键入 [[bash myfile.sh]] 来运行该文件
      • 好吧,好消息...至少这次它会迭代,它甚至可以在第一个图像上工作,然后我得到一些来自可执行文件正在使用的软件的错误。我不明白的是它试图从 inputfile0000 开始,我们告诉它从 inputfile0022.bmp 开始。我得到的唯一输出图像是 outputfile0000.bmp。这是我保存为 threshold.sh 的 bash 文件:#! /bin/bash for ((a=022; a
      • 我不确定发生了什么,但我看到一个问题...对于 printf 语句中的每个引用,您需要给出一个参数(即,您应该有 $a $a 而不是一个.
      • 耶唧!!!那成功了!尽管设置了 a=22,它仍然尝试从 input0000.bmp 开始,但如果我厌倦了抛出 21 个异常,我可以做一些简单的代码来更改文件的名称以从 0 开始。感谢您的帮助。
      【解决方案4】:

      您可以利用xargs 进行迭代:

      ls | xargs -i ./filter {} {}_out lower upper
      

      注意:

      • {} 对应管道输出的一行,这里是输入文件名。
      • 输出文件将使用后缀“_out”命名。

      【讨论】:

        【解决方案5】:

        您可以在 shell 中测试 AS-IS

        for i in *; do
            echo "$i" | tr '[:lower:]' '[:upper:]'
        done
        

        如果您有特殊的路径,请将 * 更改为您的路径 + a glob :例如:

        for i in /home/me/*.exe; do ...
        

        http://mywiki.wooledge.org/glob

        【讨论】:

        • 已编辑以解释这种可能性 =)
        • 嘿 sputnick,你能帮我理解你上面写的代码吗?我可以看到您有一个 for 循环遍历所有内容,但看不到您曾在哪里调用可执行文件来处理图像。你能给我更多的细节和解释吗?感谢您的帮助和帖子。在这么短的时间内得到这么多帮助真是太好了。
        • @user1452373 我相信他给出了一个关于直接从 shell 执行 for 循环的一般示例,以展示与实际执行相反的情况。我觉得在执行之前测试任何涉及循环的文件操作是一个好习惯。
        【解决方案6】:

        同时添加输出图像的名称,例如filtered_filename0055.bmp

        for i in *; do
            ./filter $i filtered_$i lower upper
        done
        

        【讨论】:

        • 我猜这会覆盖源文件。
        • 如果文件中有空格怎么办?然后该命令将解析为./filter file withspace filtered_file withspace lower upper。你可能应该在使用它时引用"$i"
        • @TimPote 只是试图根据问题信息使其尽可能简单。但是,引号会使其更好地检查文件扩展名和目录。
        • 如果 glob 模式捕获的文件之一包含空格,则传递给 ./filter 的参数数量会发生变化。
        猜你喜欢
        • 2014-07-03
        • 1970-01-01
        • 1970-01-01
        • 2015-08-16
        • 2019-08-04
        • 2016-04-05
        • 2022-01-06
        • 1970-01-01
        • 2011-05-09
        相关资源
        最近更新 更多