我需要编写一个用不同的参数启动程序的脚本,但我是Bash的新手。我用以下方式开始我的程序:
./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并启动我的程序。
答案 0 :(得分:586)
首先注意几个注意事项:当你使用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
- &gt; file
)如果您需要使用Data/file.txt
代替/Data/file.txt
运行MyProgram,请使用"${filename#/}"
删除前导斜杠。另一方面,如果您想要扫描Data
而不是/Data
,请使用for filename in Data/*.txt
。
答案 1 :(得分:240)
很抱歉对线程进行了解析,但是每当你通过globbing迭代文件时,最好避免使用glob不匹配的极端情况(这会使循环变量扩展为(不匹配)glob模式字符串本身)。
例如:
for filename in Data/*.txt; do
[ -e "$filename" ] || continue
# ... rest of the loop body
done
答案 2 :(得分:67)
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 parameter expansion)会删除前一个/
的前导路径名。
base=${name%.txt}
替换会删除尾随.txt
。如果扩展可以变化,这有点棘手。
答案 3 :(得分:3)
您可以将finds null分隔的输出选项与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的输出用于设置变量
答案 4 :(得分:-2)
看起来您正在尝试执行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
或者猛击
#!/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