我需要写一个脚本,启动我的程序与不同的参数。我开始我的程序:

./MyProgram.exe Data/data1.txt [Logs/data1_Log.txt]。

下面是我想要做的伪代码:

for each filename in /Data do
  for int i = 0, i = 3, i++
    ./MyProgram.exe Data/filename.txt Logs/filename_Log{i}.txt
  end for
end for

我如何从第一个参数创建第二个参数,使它看起来像dataABCD_Log1.txt并启动我的程序?


当前回答

首先需要注意的是:当您使用Data/data1.txt作为参数时,它真的应该是/Data/data1.txt(带有前导斜杠)吗?另外,外部循环应该只扫描.txt文件,还是/Data中的所有文件?下面是答案,假设只有/Data/data1.txt和.txt文件:

#!/bin/bash
for filename in /Data/*.txt; do
    for ((i=0; i<=3; i++)); do
        ./MyProgram.exe "$filename" "Logs/$(basename "$filename" .txt)_Log$i.txt"
    done
done

注:

/Data/*.txt扩展到/Data中的文本文件路径(包括/Data/ part) $(…)运行shell命令并将其输出插入到命令行中 basename somepath .txt输出somepath的基本部分,从结尾删除。txt(例如/Data/file.txt ->文件)

如果你需要用Data/file.txt而不是/Data/file.txt运行MyProgram,使用"${filename#/}"来移除前面的斜杠。另一方面,如果你想扫描的是Data而不是/Data,只需在Data/*.txt中使用for文件名。

其他回答

您可以使用find的空分隔输出选项和read来安全地遍历目录结构。

#!/bin/bash
find . -type f -print0 | while IFS= read -r -d $'\0' file;
  do echo "$file" ;
done

在你的案例中,

#!/bin/bash
find . -maxdepth 1 -type f  -print0 | while IFS= read -r -d $'\0' file; do
  for ((i=0; i<=3; i++)); do
    ./MyProgram.exe "$file" 'Logs/'"`basename "$file"`""$i"'.txt'
  done
done

此外,

#!/bin/bash
while IFS= read -r -d $'\0' file; do
  for ((i=0; i<=3; i++)); do
    ./MyProgram.exe "$file" 'Logs/'"`basename "$file"`""$i"'.txt'
  done
done < <(find . -maxdepth 1 -type f  -print0)

将在脚本(进程)的当前范围内运行while循环,并允许在需要时使用find的输出来设置变量。

它看起来像你正在尝试执行一个Windows文件(.exe)。当然你应该使用PowerShell。无论如何,在Linux Bash shell上,简单的一行程序就足够了。

[/home/$] for filename in /Data/*.txt; do for i in {0..3}; do ./MyProgam.exe  Data/filenameLogs/$filename_log$i.txt; done done

或者在Bash脚本中:

#!/bin/bash

for filename in /Data/*.txt;
   do
     for i in {0..3};
       do ./MyProgam.exe Data/filename.txt Logs/$filename_log$i.txt;
     done
 done

首先需要注意的是:当您使用Data/data1.txt作为参数时,它真的应该是/Data/data1.txt(带有前导斜杠)吗?另外,外部循环应该只扫描.txt文件,还是/Data中的所有文件?下面是答案,假设只有/Data/data1.txt和.txt文件:

#!/bin/bash
for filename in /Data/*.txt; do
    for ((i=0; i<=3; i++)); do
        ./MyProgram.exe "$filename" "Logs/$(basename "$filename" .txt)_Log$i.txt"
    done
done

注:

/Data/*.txt扩展到/Data中的文本文件路径(包括/Data/ part) $(…)运行shell命令并将其输出插入到命令行中 basename somepath .txt输出somepath的基本部分,从结尾删除。txt(例如/Data/file.txt ->文件)

如果你需要用Data/file.txt而不是/Data/file.txt运行MyProgram,使用"${filename#/}"来移除前面的斜杠。另一方面,如果你想扫描的是Data而不是/Data,只需在Data/*.txt中使用for文件名。

无论何时通过globbing遍历文件,最好避免出现glob不匹配的情况(这会使循环变量扩展到(不匹配的)glob模式字符串本身)。

例如:

for filename in Data/*.txt; do
    [ -e "$filename" ] || continue
    # ... rest of the loop body
done

参考:Bash陷阱

for file in Data/*.txt
do
    for ((i = 0; i < 3; i++))
    do
        name=${file##*/}
        base=${name%.txt}
        ./MyProgram.exe "$file" Logs/"${base}_Log$i.txt"
    done
done

name=${file##*/}替换(shell参数展开)删除前导路径名直到最后一个/。

base=${name%.txt}替换删除了后面的.txt。如果扩展可以变化,那就有点棘手了。