foo
ファイルパスを使用し、ファイルを読み込み、いくつかの変更を適用し、変更されたファイルを標準出力に出力するスクリプトを作成しました。
foo src/file.foo > dest/file.changed.foo # works fine
cat src/file.foo | foo > dest/file.changed.foo # also works fine
これで、このコマンドをディレクトリ内の複数のファイルに適用し、各ファイルに対して次のことを試みます。
src/file.foo --> foo --> ターゲット/file.changed.foo
find src -name '*.foo' \
-exec bash -c 'for x; do dest=${x/src/dest}; foo ${x} > ${dest/\.foo$/.changed.foo}; done' _ {} +
上記の方法は効果がありますが、問題は日常的に使用するには複雑すぎるということです。もっと簡単な方法はありませんか?foo
仕事を複雑にする方法ではないかと思います。
ベストアンサー1
再帰ワイルドカードを使用すると、入力と操作が大幅に削減されます。バッシュでは、次のように入力してください。shopt -s globstar
あなたの.bashrc
。 ksh93では再帰ワイルドカードが必要ですset -o globstar
。 zshではデフォルトで使用できます。 Bashでは、再帰ワイルドカードはディレクトリへのシンボリックリンクでも再帰されます。
文字列操作を保存するには、まずソースツリーの上部(またはターゲットツリーの上部)に変更します。
cd foo
for x in **/*.foo; do foo "$x" >"../dest/${x%.*}.changed.foo"; done
ファイル名にスペースやワイルドカードが含まれていない場合は、二重引用符を省略できます。
zshは二重引用符を必要とせず、現在のディレクトリを変更しなくてもより多くの入力を節約できます。
for x in src/**/*.foo; do foo $x >../dest/${${x#*/}%.*}.changed.foo; done
for x in src/**/*.foo; do foo $x >../dest/${x#*/}:r.changed.foo; done
for x (src/**/*.foo) foo $x >../dest/${x#*/}:r.changed.foo
これを頻繁に実行する場合は、たとえばGNUmakefileでビルドルールを定義する必要があります(タブを使用して8つのスペースを使用します)。
source_files = $(shell find src -name '*.foo')
destination_files = $(patsubst src/,dest/,$($(source_files)%.foo=.changed.foo))
default: all-foo
all-foo: $(destination_files)
dest/%.changed.foo: src/%.foo
foo $< >$@