Bagaimana cara menambahkan header lisensi secara rekursif untuk semua file .h dan .cpp dalam direktori


19

Saya mencoba menambahkan header lisensi ke semua file header dan sumber file dalam direktori proyek menggunakan for for. Ini tidak berfungsi, apakah ada pendekatan lain yang digunakan sed?


1
pbm

Jawaban:


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

1
Harus disebutkan bahwa Anda harus mengaktifkan globstarbash agar ini berfungsi.
Chris Down

Dan Anda perlu bash> 4.0 (mis., Mac OS X dan RedHat 5 masih di 3.X)
Matteo

11

Ini kurang lebih hanya komentar panjang tentang jawaban Daniel Serodio . Saya mulai menulisnya sebagai komentar, tetapi dengan cepat menjadi terlalu besar ...

Agar bash glob menjadi rekursif, itu membutuhkan shopt -s globstar. Anda harus mengaktifkan globstar, jika **tidak, tidak akan berfungsi. Opsi shell globstar diperkenalkan ke versi 4 dari bash.

Untuk menghindari pemrosesan direktori seperti my.cpp/, gunakan tes [[ -f $f ]]... Ketika tes berada dalam tanda kurung ganda, variabel tidak perlu dikutip ganda.

Anda juga dapat mempertimbangkan kemungkinan tidak ada file yang cocok dengan menggunakan shopt -s nullglob, yang memungkinkan pola yang tidak cocok dengan file untuk memperluas ke string nol, daripada diri mereka sendiri.

Untuk menangani beberapa pola, Anda dapat rantai pola gumpal: **/*.cpp **/*.h, tapi mungkin Preferably, ketika shell pilihan extglob adalah pada melalui shopt -s extglob, Anda dapat menggunakan konstruksi seperti seperti **/*.@(cpp|h)yang menghindari melewati beberapa atas sistem file; satu kali untuk setiap pola.

Jika Anda ingin .filesdimasukkan, gunakan .*.cppdll, atau gunakanshopt -s dotglob

Untuk menangani pengubahan file dengan aman yang sedang disalurkan, gunakan spongedari paket moreutils(menghemat Anda untuk membuat file temp Anda sendiri)


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

Jawaban yang jauh lebih lengkap dan informatif daripada yang lain, +1
n0pe

+1, tetapi [[dapat menangani null dengan anggun $f.
enzotib

@enzotib. Terima kasih. Saya tidak yakin dari mana saya mendapatkan ide itu. Pasti dari cara kurung siku tunggal bekerja (tidak) ... misalnya unset x; [ -f $x ] && echo exists laporan "ada" ... (tetap)
Peter.O

Karena versi 4 dari bash belum umum tetapi saya akan mengganti **/*.@(cpp|h)dengan$( find . -name "*.h" -name "*.cpp")
Matteo

3

@Fred terima kasih, @maxmackie, @enzotib.

Tolong periksa prosedur yang saya ikuti.

#!/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   

jika tidak, tajuk lisensi akan disalin ke beberapa kali.

Tolong sarankan saya pola untuk pergi melalui semua header dan sumber di direktori proyek dan subdirektori.

Saya tidak bisa mengerti sepenuhnya apa yang telah disarankan @fred.


Secara umum, kode Anda terlihat oke. Saya akan lebih spesifik tentang mengidentifikasi lokasi yang tepat dari "Hak Cipta", misalnya. tentukan nomor baris dan posisi pada baris itu. Anda dapat mencegah sed membaca seluruh file dengan berhenti pada baris di mana Anda berharap menemukan "Hak Cipta" ... misalnya. targln=2; findln=$(sed -rne $targln'{\|// Copyright|=;q}' "$f"); if ((findln==targln));then... tapi, tentu saja, di atas dan di luar semua yang lain, ujilah secara menyeluruh terlebih dahulu ... PS. Merupakan hal yang wajar untuk kursus di Unix & Linux untuk mengirim tambahan seperti itu dalam pertanyaan awal Anda, bukan sebagai jawaban ...
Peter.O

1
Beberapa saran: hapus tanda kurung di sekitar grep, tambahkan -qopsi ke grep. Selalu tambahkan tanda kutip ganda di sekitar $f.
enzotib

1
Kutipan sangat penting, jika tidak Anda kemungkinan akan digigit oleh kata splitting. Sebagai aturan dasar, kutip setiap ekspansi kecuali Anda tahu bahwa pemisahan kata atau interpretasi lainnya tidak akan dilakukan oleh shell.
Chris Down

3

Anda dapat melakukan ini dengan exatau edjika Anda lebih suka (Anda tidak boleh melakukan ini dengan sedseperti yang Anda minta, seddirancang untuk mengedit stream, -iadalah ide yang buruk karena berbagai alasan):

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

Mengapa itu sed -iide yang buruk?
Daniel Serodio

@DanielSerodio Secara default, sed -imemecah symlink dan hardlink, menghasilkan perilaku yang tidak terduga. Paling-paling itu tidak intuitif, paling buruk itu berbahaya secara aktif.
Chris Down

2

Jika Anda memiliki header_filedengan konten yang diinginkan:

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

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.