ディレクトリ内のファイルをループしてパスを変更し、ファイル名にサフィックスを追加する方法

異なる引数でプログラムを開始するスクリプトを書く必要があるのですが、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 `file`)。

もし、`Data/file.txt`ではなく、`Data/file.txt`でMyProgramを実行する必要がある場合は、`"${filename#/}"`を使って、先頭のスラッシュを削除します。逆に、スキャンしたいのが本当に`Data`ではなく`Data/*.txt`のファイル名を対象とする場合は、`for filename in Data/*.txt`とすればよいのです。
解説 (7)

スレッドを再利用して申し訳ありませんが、グロブを使ってファイルを反復処理する場合は、グロブがマッチしない(ループ変数が(マッチしない)グロブパターン文字列そのものに展開される)というコーナーケースを避けるのが良い方法です。

例えば

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

参考にしてください。Bash Pitfalls

解説 (9)
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` を削除します。 拡張子が異なる場合には、少し厄介です。

解説 (2)