ディレクトリ内のすべての.hおよび.cppファイルにライセンスヘッダーを再帰的に追加する方法


19

forループを使用して、プロジェクトディレクトリ内のすべてのヘッダーファイルとソースファイルにライセンスヘッダーを追加しようとしています。これは機能していませんが、他のアプローチを使用していsedますか?


1
非常によく似たケース:unix.stackexchange.com/questions/20577/…–
pbm

回答:


14
for f in **/*.cpp; do
  cat header_file $f > $f.new
  mv $f.new $f
done

1
これを機能させるにはglobstar、bashで有効にする必要があることに注意してください。
クリスダウン

そして、あなたはbashの> 4.0(例えば、Mac OS XとRedHatの5は3.Xに残っている)必要があること
マッテオ

11

これは多かれ少なかれ、ダニエル・セロディオの答えに対する単なる拡張解説です。コメントとして書き始めましたが、すぐに大きくなりすぎました...

bash globを再帰的にするには、が必要shopt -s globstarです。globstarを有効にする必要があります。有効に**しないと機能しません。globstar shellオプションは、bashのバージョン4に導入されました。

などのディレクトリの処理を回避my.cpp/するには、test [[ -f $f ]]...を使用します。テストが二重角括弧で囲まれている場合、変数を二重引用符で囲む必要はありません。

またshopt -s nullglob、を使用することにより、一致するファイルがない可能性を考慮することができます。これにより、ファイルに一致しないパターンを、それ自体ではなくヌル文字列に展開できます。

複数のパターンを処理するには、globパターンを連鎖させることができます。**/*.cpp **/*.hただし、おそらくシェルオプションextglobviaオンになっているshopt -s extglob場合は**/*.@(cpp|h)、ファイルシステムの複数のパスを回避するような構造を使用できます。パターンごとに1回。

.files含めたい場合、使用する場合.*.cpp、または使用する場合shopt -s dotglob

パイプされているファイルの変更を安全に処理するには、spongefromパッケージを使用しますmoreutils(独自の一時ファイルを作成する必要がなくなります)


printf "// The License\n\n" > /tmp/$USER-license

shopt -s globstar nullglob extglob
for f in **/*.@(cpp|h) ;do
  [[ -f $f ]] && cat "/tmp/$USER-license" "$f" | sponge "$f"
done

他の回答よりもはるかに完全で有益な回答、+ 1
n0pe

+1。ただし[[、nullを適切に処理できます$f
-enzotib

@enzotib。ありがとう。私はそのアイデアを得たかどうかわかりません。それはどのように、単一の角括弧の作品からされている必要があります...例えば(しない)unset x; [ -f $x ] && echo exists の報告書は、「存在」...(固定)
Peter.O

bashのバージョン4が主流ではないので、まだ私が代わります**/*.@(cpp|h)$( find . -name "*.h" -name "*.cpp")
マッテオ

3

ありがとう、@ fred、@ maxmackie、@ enzotib。

私が従った手順を確認してください。

#!/bin/sh
# script to copy the headers to all the source files and header files
for f in *.cpp; do
  if (grep Copyright $f);then 
    echo "No need to copy the License Header to $f"
  else
    cat license.txt $f > $f.new
    mv $f.new $f
    echo "License Header copied to $f"
  fi 
done   

それ以外の場合、ライセンスヘッダーは複数回コピーされます。

プロジェクトディレクトリとサブディレクトリのすべてのヘッダーとソースを調べるパターンを提案してください。

@fredが示唆したことを完全に理解できませんでした。


一般的に、コードは正常に見えます。「著作権」の正確な場所を特定することについて、より具体的になります。行番号とその行の位置を指定します。「著作権」が見つかると予想される行で終了することにより、sedがファイル全体を読み取らないようにすることができます。 targln=2; findln=$(sed -rne $targln'{\|// Copyright|=;q}' "$f"); if ((findln==targln));then...しかし、もちろん、他のすべてのものを超えて、最初に徹底的にテストしてください... PS。UnixおよびLinuxのコースでは、答えとしてではなく、元の質問にそのような追加を投稿するのが
適切

1
いくつかのアドバイス:括弧を削除しgrep、に-qオプションを追加しますgrep。常に二重引用符を追加します$f
エンゾチブ

1
引用符は非常に重要です。そうしないと、単語の分割に引っかかる可能性が高くなります。基本的なルールとして、単語の分割やその他の解釈がシェルによって実行されないことがわかっている場合を除き、すべての展開を引用してください。
クリスダウン

3

exまたはed、必要に応じてこれを行うことができます(sed要求どおりにこれを行うべきではありません。sedストリームを編集するように設計されている-iため、さまざまな理由で悪い考えです)。

shopt -s globstar

for _file in **/*.@(cpp|h); do
    ed -s "${_file}" << EOF
0a
/* This file is licensed under the foo license.
   All copyright strictly enforced by the copyright monster. */
.
w
EOF
    done

なぜsed -i悪い考えですか?
ダニエルセロディオ

@DanielSerodioデフォルトでsed -iは、シンボリックリンクとハードリンクが解除され、予期しない動作が発生します。せいぜい直感的ではなく、さらに悪いことに積極的に有害です。
クリスダウン

2

header_file希望するコンテンツをお持ちの場合:

find -name '*.cpp' -exec bash -c 'cat header_file \{} > \{}.new; mv \{}.new  \{}' \;
find -name '*.h' -exec bash -c 'cat header_file \{} > \{}.new; mv \{}.new  \{}' \;

1
#!/bin/bash

for i in `find . -name '*.[m|h]'` # or whatever other pattern...
do
  echo $i
  if ! grep -q Copyright $i
  then
    cat copyright.txt $i >$i.new && mv $i.new $i
  fi
done
enter code here

0

Gerhard Gappmeierのブログ-ソースファイルのファイルヘッダーを再帰的に置き換えるHowto

ブログの投稿にはtar.gz、必要なファイルを含むファイルが添付されています。

このheader.templateファイルには、カスタムコメントを記述できるファイルがあり、複数行にわたることができます。

remove_header.awk既存のヘッダーを新しいヘッダーに置き換えるスクリプトがあります。

実行するには:

find . -name "*.h" -exec ~/rh/replace_header.sh {} \;
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.