Cách đăng ký tiêu đề giấy phép theo cách đệ quy cho tất cả các tệp .h và .cpp trong một thư mục


19

Tôi đang cố gắng thêm tiêu đề giấy phép cho tất cả các tệp tiêu đề và tệp nguồn trong thư mục dự án bằng vòng lặp for. Điều này không hiệu quả, có cách tiếp cận nào khác sedkhông?


1
Trường hợp rất giống nhau: unix.stackexchange.com/questions/20577/ từ
pbm

Câu trả lời:


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

1
Cần phải đề cập rằng bạn cần bật globstarbash để làm việc này.
Chris Xuống

Và bạn cần bash> 4.0 (ví dụ: Mac OS X và RedHat 5 vẫn còn trên 3.X)
Matteo

11

Đây ít nhiều chỉ là một bình luận mở rộng về câu trả lời của Daniel Serodio . Tôi bắt đầu viết nó như một bình luận, nhưng nó nhanh chóng phát triển quá lớn ...

Để một bash toàn cầu được đệ quy, nó đòi hỏi shopt -s globstar. Bạn phải kích hoạt globalstar, nếu **không thì không hoạt động. Tùy chọn shell globalstar được giới thiệu cho phiên bản 4 của bash.

Để tránh xử lý một thư mục như my.cpp/, hãy sử dụng kiểm tra [[ -f $f ]]... Khi kiểm tra nằm trong dấu ngoặc vuông, các biến không cần phải được trích dẫn kép.

Bạn cũng có thể xem xét khả năng không có tệp phù hợp bằng cách sử dụng shopt -s nullglob, cho phép các mẫu không khớp với tệp nào mở rộng thành chuỗi null, thay vì chính chúng.

Để xử lý nhiều mẫu, bạn có thể chuỗi các mẫu glob: **/*.cpp **/*.h, nhưng có lẽ tốt hơn là, khi vỏ tùy chọn extglobtrên qua shopt -s extglob, bạn có thể sử dụng các cấu trúc như vậy như **/*.@(cpp|h)mà tránh nhiều đi ngang qua hệ thống tập tin; một lần cho mỗi mẫu.

Nếu bạn muốn .filesđược bao gồm, sử dụng .*.cppvv, hoặc sử dụngshopt -s dotglob

Để xử lý một cách an toàn việc sửa đổi tệp đang được xử lý, hãy sử dụng spongetừ gói moreutils(nó giúp bạn tiết kiệm được nhu cầu tạo tệp tạm thời của riêng bạn)


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

Câu trả lời đầy đủ và nhiều thông tin hơn câu trả lời khác, +1
n0pe

+1, nhưng [[duyên dáng có thể xử lý null $f.
enzotib

@enzotib. cảm ơn. Tôi không chắc là tôi có ý tưởng đó từ đâu. Nó phải xuất phát từ cách hoạt động của khung vuông đơn (không) ... ví dụ: unset x; [ -f $x ] && echo exists báo cáo "tồn tại" ... (đã sửa)
Peter.O

Vì phiên bản 4 của bash không phải là chủ đạo nhưng tôi sẽ thay thế **/*.@(cpp|h)bằng$( find . -name "*.h" -name "*.cpp")
Matteo

3

Cảm ơn bạn @fred, @maxmackie, @enzotib.

Bạn có thể vui lòng kiểm tra các thủ tục tôi đã làm theo.

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

nếu không, tiêu đề giấy phép sẽ được sao chép thành nhiều lần.

Vui lòng gợi ý cho tôi một mẫu để đi qua tất cả các tiêu đề và nguồn trong thư mục dự án và thư mục con.

Tôi không thể hiểu đầy đủ những gì @fred đã đề xuất.


Nói chung, mã của bạn trông ổn. Tôi sẽ cụ thể hơn về việc xác định vị trí chính xác của "Bản quyền", ví dụ. chỉ định số dòng và vị trí trên dòng đó. Bạn có thể ngăn không cho sed đọc toàn bộ tệp bằng cách thoát khỏi dòng mà bạn muốn tìm "Bản quyền" ... ví dụ. targln=2; findln=$(sed -rne $targln'{\|// Copyright|=;q}' "$f"); if ((findln==targln));then... nhưng, tất nhiên, trên hết và hơn tất cả mọi thứ khác, hãy kiểm tra kỹ lưỡng trước ... PS. Đây là ngang bằng với khóa học tại Unix & Linux để đăng các phần bổ sung như vậy trong câu hỏi ban đầu của bạn, không phải là một câu trả lời ...
Peter.O

1
Một số lời khuyên: xóa dấu ngoặc đơn xung quanh grep, thêm -qtùy chọn vào grep. Luôn luôn thêm dấu ngoặc kép xung quanh $f.
enzotib

1
Trích dẫn là rất quan trọng, nếu không bạn sẽ có khả năng bị cắn bởi chia tách từ. Như một quy tắc cơ bản, trích dẫn mọi mở rộng trừ khi bạn biết rằng việc tách từ hoặc giải thích khác sẽ không được thực hiện bởi trình bao.
Chris Xuống

3

Bạn có thể làm điều này với exhoặc ednếu bạn thích (bạn không nên làm điều này với sedyêu cầu của bạn, sedđược thiết kế để chỉnh sửa luồng, -ilà một ý tưởng tồi vì nhiều lý do):

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

Tại sao là sed -imột ý tưởng tồi?
Daniel Serodio

@DanielSerodio Theo mặc định, sed -iphá vỡ liên kết tượng trưng và liên kết cứng, dẫn đến hành vi không mong muốn. Tốt nhất là nó không trực quan, tệ hơn là nó có hại tích cực.
Chris Down

2

Nếu bạn có một header_filenội dung mong muốn:

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

Blog của Gerhard Gappmeier - Cách thay thế đệ quy các tiêu đề tệp của các tệp nguồn

Bài đăng trên blog đã đính kèm một tar.gztệp, chứa các tệp cần thiết.

Nó có một header.templatetập tin, nơi bạn có thể viết một bình luận tùy chỉnh, nó có thể trải dài trên nhiều dòng.

Nó có một remove_header.awkkịch bản thay thế các tiêu đề hiện có bằng tiêu đề mới.

Để chạy nó:

find . -name "*.h" -exec ~/rh/replace_header.sh {} \;
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.