3列形式(タブで区切られた)のデータを含むファイルの束を含む14個のディレクトリを持つディレクトリ構造があります。 findとawkを使用して、これらの各ファイルから2番目の列を抽出し、同じファイル名で異なるルートフォルダーに出力するつもりでした。ここに私のディレクトリのスケッチがあります。
data/all-> AA、AB、AC、AD ...(A *は、AA100.txt、AA101.txtなどの3列形式で保存されたデータを含むファイルを含むフォルダーです...)
同じ名前の変更された(1列の)ファイルが必要ですが、すべて新しいルートディレクトリにありますdata/pos(data/all /ではなく)-> AA、AB、AC、AD ...(再び、それぞれにA * 100.txt、A * 101 ...が含まれています)
Find -execを使用してawkコマンドを実行しようとしましたが、ファイルを適切な場所に出力する際に問題が発生します。
データ/すべて/にあるとき
find * -type f -exec awk '{print $ 2}' '{}'> ../ pos/'{}' \;
ただし、入力ファイルのワイルドカードとしての{}は、ファイルを出力するときに機能しないようです。
私は何が間違っているのですか? (私はubuntuサーバーにいます)
必要なのがすべてのファイルである場合は、検索せずに試すことができます。 data/all/
にいる間に、これを実行します。
for file in ./*; do awk '{print$2}' "$file" > "../pos/$(basename $file)"; done
/data/all
の下の階層全体のファイルをカバーしたい場合、bashを使用している場合はglobstar
オプションを有効にして(これはzshで「うまくいく」と思います)、**
を使用してすべてのファイルを照合できます:
shopt -s globstar
for file in ./**; do awk '{print$2}' "$file" > "../pos/$(basename $file)"; done
私は何が間違っているのですか?
リダイレクト> ../pos/'{}'
をfind
またはawk
によって処理されたかのように使用していますが、リダイレクトはシェルによって処理されます。あなたの場合、それはfind
全体の出力のみをリダイレクトできることを意味します(awk
の出力はリダイレクトできません)。
通常、find
の開始パスに*
のようなワイルドカードを使用する必要はないことに注意してください。一般的な方法はfind .
でしたか、それともfind *
の理由はありますか?
ここでは、Jacobo de Veraによるソリューションとは対照的に、find
の柔軟性を維持します。シェルループでawk
を実行します。
find . -type f -print0 |
while read -r -d $'\0' x; do
awk '{print $2}' "$x" > "../pos/$(basename "$x")"
done
-exec
を使用した元の方法は、すべてのファイルに対してawk
に加えてシェルが起動され、マルチレベルのエスケープがここではかなり複雑になるため、効率が低下します。
find . -type f -exec sh -c 'awk "{print \$2}" "{}" > "../pos/{}"' \;
awk
内でリダイレクトを行う別の解決策もあります。