異なる引数でプログラムを開始するスクリプトを書く必要があるのですが、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
どうやって最初の引数から2番目の引数を作り、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/ の部分を含む)。$( ... )
はシェルコマンドを実行し、その出力をコマンドラインのその位置に挿入します。は、somepath のベース部分から .txt を取り除いたものを出力します(例:
/Data/file.txt->
file`)。もし、Data/file.txt
ではなく、Data/file.txt
でMyProgramを実行する必要がある場合は、"${filename#/}"
を使って、先頭のスラッシュを削除します。逆に、スキャンしたいのが本当にData
ではなくData/*.txt
のファイル名を対象とする場合は、for filename in Data/*.txt
とすればよいのです。
スレッドを再利用して申し訳ありませんが、グロブを使ってファイルを反復処理する場合は、グロブがマッチしない(ループ変数が(マッチしない)グロブパターン文字列そのものに展開される)というコーナーケースを避けるのが良い方法です。
例えば
for filename in Data/*.txt; do
[ -e "$filename" ] || continue
# ... rest of the loop body
done
参考にしてください。Bash Pitfalls
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##*/}という置換([シェルのパラメータ展開](http://www.gnu.org/software/bash/manual/bash.html#Shell-Parameter-Expansion))を行うと、先頭のパス名が最後の
/` まで削除されます。
base=${name%.txt}とすると、末尾の
.txt` を削除します。 拡張子が異なる場合には、少し厄介です。