入力ディレクトリを繰り返し探索し、各ファイルに対して別々のディレクトリ階層の下にそのファイルを生成するスクリプトを作成したいと思います。
たとえば、ファイルはになります。input/a/b/c.txt
これにより、入力ディレクトリの名前を出力ディレクトリの名前に変更するきちんとした方法は何ですか?output/a/b/c.txt
input/a/d.txt
output/a/d.txt
私が知っているどちらも正しいとは思わない。 1つ目は、#
パラメータ拡張を使用してファイルプレフィックスを削除することです。ただし、入力ディレクトリ名に特殊文字が含まれている場合(たとえば、*
入力ディレクトリ名が変数にある場合)も読みにくくなります。
find input -type f | while read -r infile; do
outfile=output/"${infile#input/}"
mkdir -p "$(dirname "$outfile")"
some-program "$infile" > "$outfile"
done
私が試したもう一つの方法は、入力ディレクトリに行き、すべての項目に絶対リンクを使用することでした。ただし、これには複数の呼び出しが必要でcd
あり、また依存的であるため、readlink
移植性が最善ではありません。
abspwd=$(pwd)
absinput=$(readlink -f input)
absoutput=$(readlink -f output)
cd "$absinput"
find . -type f | while read infile; do
outfile="$absoutput/$infile"
mkdir -p "$(dirname "$outfile")"
some-program "$infile" > "$outfile"
done
cd "$abspwd"
別の方法がありますか?これを行うより簡単な方法があるはずです。
ベストアンサー1
ほぼすべて来ました。
出力に入力されたディレクトリ構造をコピーするrsyncを配置します。その後、検索パイプラインが実行されると、一部のプログラムの出力が正しい場所に表示されます。
TOP="input"
rsync -a -f'+ */' -f'- *' "$TOP"/ output/
find "$TOP" -type f | while IFS= read -r infile; do
outfile=output/${infile#"$TOP"/}
some-program "$infile" > "$outfile"
done
改行を含むファイル名は正しく処理されません。そのような場合が必要だと思われる場合は、より多くのコードを使用して処理できます。あるディレクトリから別のディレクトリにファイル名を移行することに注意を配布したくありません。