Bashスクリプトは、条件が満たされると、すべてのファイルの先頭にテキストを配置します。

Bashスクリプトは、条件が満たされると、すべてのファイルの先頭にテキストを配置します。

次の場合にのみ、すべてのサブディレクトリのすべてのファイルの先頭にテキストを配置するbashスクリプトを作成しようとしています。

  1. ファイルにテキストが含まれていません。
  2. ファイルには、会社名、Riverという単語、またはSystemsという単語が含まれています。

これが私が今まで持っているものです:

for i in $(find -name *.cpp -type f -print)
do 
if ! grep -r 'This document contains technical data' $i && grep -r 'company name' $1 || grep-r 'River' $i || grep -r 'Systems' $i; then
#add text

これで、キーワードが含まれていないファイルは期待どおりに変更されませんが、テキストとキーワードがすでに含まれているファイルの場合は変更されます。 ||周りに[]ステートメントを使用してみましたが、結果は同じです。どんな提案がありますか?

ベストアンサー1

find . -name '*.cpp' -type f \
  ! -exec grep -qF 'This document contains technical data' {} ';' \
  -exec grep -qFe River -e 'company name' -e Systems {} ';' \
  -exec sed -i '1i\
This document contains technical data' {} +

(FreeBSD / macos 'sed -iに置き換えられます)sed -i ''sed

grepあるいは、GNUを使用すると、GNUはより効率的ですxargs

grep --include='*.cpp' -rFlZ -e River -e 'company name' -e Systems . |
  xargs -r0 grep -FLZ 'This document contains technical data' |
  xargs -r0 sed -i '1i\
This document contains technical data.'

試みに関するいくつかの注意:

  • find -print出力を後処理できません。
  • パラメータ拡張は、以下で引用する必要があります。bash
  • -r(GNU拡張)再帰的grep は、独自のタスクに加えて他のタスクをgrep実行するには、ディレクトリを ping するときにのみ使用できます (ディレクトリからファイルを検索し、そのファイルでパターンを探します)。findgrep
  • *特殊文字シェル、そこからワイルドカードがトリガされます。*.cppにリテラルを渡すことができるように引用されていることを確認する必要がありますfind
  • 一致するすべての行をチェックせずにファイル内のパターンが一致できるかどうかを確認するには、このオプションを使用します-q。印刷をスキップするだけでなく、grep最初の一致を確認しないので、より効率的です。(GNU拡張)は同じ最適化を持っています-l-L前者は、パターンが見つかるとファイルパスを印刷し、後者はパターンが見つからない場合はファイルパスを印刷します。
  • 固定文字列を検索するにはF(正規表現マッチングを実行するのではなく)、この-Fオプションを使用して正規表現演算子をエスケープする必要はありません。
  • 、をgrep foo file || grep bar file使用せずに1つのパターンで複数のパターンを見つけることができます。find'(' -exec grep -q foo {} ';' -o -exec grep -q bar {} ';' ')'grepまたは一度にスタイリッシュgrep -e foo -e bar file他の方法
  • orともgrep -F River一致しますRiverside。一致するオプションのみを追加できます。WindRiver-wみんな単語(単語は数字や下線などの単語以外の文字で区切る必要があり、単語以外の文字はその他の文字です)。

おすすめ記事