時間が経つにつれて、私は同じパターンを繰り返し経験しました。一種のディレクトリ構造がありました。
example/
├── a
│ └── c
│ ├── d.txt (120k)
│ └── e.txt (60k)
└── b
└── f.txt (280k)
example_grepped
たとえば、各ファイルにコマンドを適用して、ファイルを別のディレクトリに「コピー」したいとします。cp
たとえばgrep ERROR
、構造は同じですが、ファイルがgrep
。
example_grepped/
├── a
│ └── c
│ ├── d.txt (1k)
│ └── e.txt (0b)
└── b
└── f.txt (12k)
メディアファイル(FLACからMP3へ、PNGからJPGへ)を変換するのと同じパターンです。今回は、ビルドプロセス中にさまざまなアーキテクチャ形式を変換します。
使用できる一般的なコマンドはありますか?foobar example example_grepped --command 'grep ERROR'
またはに似ていますかfoobar flacs mp3s --command 'ffmpeg -i {} {}.mp3'
?
たぶん謙虚なxargs
旗でしょうか? (パイプfind
xargs
ほぼ十分ですが、ほとんどのコマンドは、ディレクトリ構造がすでに存在すると予想しています。 )
答え1
ディレクトリ構造を別々に再作成せずに私が見つけることができる最も近い答えは、次のものを使用することです。インストールする:
cd example
find . -type f -exec sh -c 'grep ERROR {} | install -D /dev/stdin /tmp/example_grepped/{}' \;
残念ながら、上記の方法はコマンドが結果をSTDOUTに送信できる場合にのみ機能します。
答え2
この問題を解決する別の方法は、とにかく再帰的にコピーするプログラムを使用することです。確認しましたが、rsync
しばらく見た後でもコールバックオプションが見つかりませんでした。ただし、gnuにはファイルの入力を受け取るコマンドを提供するtar
オプションがあります。しかし、ファイルをどのように生成しますか?さて、というコマンドはで現在のファイル名を探します。--to-command
stdin
$TAR_FILENAME
すべてをまとめると、基本的な呼び出しは次のようになります。
tar cf - example | tar xf - --to-command="./script example_grepped 'grep-pattern'"
スクリプトの外観は次のとおりです。
#!/bin/bash
mkdir -p $(dirname "$1/$TAR_FILENAME")
grep '$2' >"$1/$TAR_FILENAME"
exit 0
この問題を解決するもう1つの方法は、コマンドラインからコマンドを実行するスクリプトにtarパイプをラップすることです。しかし、この構造を脱出するmkdir ...dirname
のは少し難しいでしょう。
答え3
#!/bin/bash
filter() {
local target_root="${@: -1}"
target_path=$(sed -E "s/[^/]*/$target_root/" <<< "$1")
target_dir=$(dirname "$target_path")
mkdir -p "$target_dir"
if [[ -f $1 ]]; then
# do your grep thing here
grep burger "$1" > "$target_path"
fi
}
export -f filter
source_root="example"
target_root="example_grepped"
find "$source_root/" -print0 | xargs -0 -I content bash -c "filter 'content' '$target_root'"
このスクリプトは、スペースを含むディレクトリとファイル名にも機能します。
ソースディレクトリ(「examples」)がある場所でこのスクリプトを実行します。
答え4
GNU Parallelを使用すると、次のことができます。
cd src
find . -type f | parallel 'mkdir -p ../dst/{//}; dostuff --input {} --output ../dst/{}'