एक निर्देशिका में सभी .hpp और .cpp फ़ाइलों के लिए पुनरावर्ती लायसेंस हैडर को कैसे प्रस्तुत करें


19

मैं एक लूप का उपयोग करके प्रोजेक्ट निर्देशिका में सभी हेडर फ़ाइलों और स्रोत फ़ाइलों के लिए एक लाइसेंस हेडर जोड़ने की कोशिश कर रहा हूं। यह काम नहीं कर रहा है, क्या कोई अन्य दृष्टिकोण का उपयोग कर रहा है 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> 4.0 (जैसे, Mac OS X और RedHat 5 अभी भी 3.X पर हैं)
Matteo

11

यह कमोबेश डैनियल सेरोडियो के उत्तर पर एक विस्तारित टिप्पणी है । मैंने इसे एक टिप्पणी के रूप में लिखना शुरू किया, लेकिन यह जल्दी से बहुत बड़ा हो गया ...

एक bash ग्लोब को पुनरावर्ती होने के लिए, इसकी आवश्यकता होती है shopt -s globstar। आपको ग्लोबस्टार को सक्षम करना होगा, अन्यथा **काम नहीं करेगा। ग्लोबस्टार शेल विकल्प को बैश के संस्करण 4 में पेश किया गया था।

एक निर्देशिका जैसे प्रसंस्करण से बचने के my.cpp/लिए, परीक्षण का उपयोग करें [[ -f $f ]]... जब परीक्षण डबल वर्ग-ब्रैकेट में होता है, तो चर को दोहरे उद्धरण चिह्नों की आवश्यकता नहीं होती है।

आप उपयोग करके कोई मेल नहीं होने वाली फ़ाइलों की संभावना पर भी विचार कर सकते हैं shopt -s nullglob, जो उन पैटर्न की अनुमति देता है जो अपने आप के बजाय नल स्ट्रिंग में विस्तार करने के लिए कोई फाइल से मेल नहीं खाते हैं।

कई पैटर्न को संभालने के लिए, आपको ग्लोब पैटर्न श्रृंखला कर सकते हैं: **/*.cpp **/*.h, लेकिन शायद अधिमानतः, जब खोल विकल्प extglob है पर के माध्यम से shopt -s extglob, आप इस तरह के निर्माणों जैसे उपयोग कर सकते हैं **/*.@(cpp|h)जो फाइल सिस्टम के साथ इसने कई गुजरता से बचा जाता है; प्रत्येक पैटर्न के लिए एक बार।

यदि आप .filesशामिल होना चाहते हैं, तो उपयोग करें .*.cpp, या उपयोग करेंshopt -s dotglob

सुरक्षित रूप से एक फ़ाइल को संशोधित करने के लिए जिसे पाइप किया जा रहा है, spongeपैकेज से उपयोग करें 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, लेकिन [[इनायत से अशक्त को संभाल सकता है $f
enzotib

@enzotib। धन्यवाद। मुझे यकीन नहीं है कि मुझे वह विचार मिला था। यह इस बात से रहा होगा कि एकल वर्ग-ब्रैकेट कैसे काम करता है (नहीं) ... उदाहरण unset x; [ -f $x ] && echo exists रिपोर्ट "मौजूद है" ... (निश्चित)
पीटर।

चूंकि बाश का संस्करण 4 मुख्य धारा नहीं है, इसलिए मैं इसके **/*.@(cpp|h)साथ$( find . -name "*.h" -name "*.cpp")
Matteo

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 ने क्या सुझाव दिया है।


सामान्य तौर पर, आपका कोड ठीक दिखता है। मैं "कॉपीराइट" के सटीक स्थान की पहचान करने के बारे में अधिक विशिष्ट होगा, उदाहरण के लिए। उस लाइन पर लाइन नंबर और स्थिति निर्दिष्ट करें। जहाँ आप "कॉपीराइट" खोजने की अपेक्षा करते हैं, उस पंक्ति को छोड़ कर आप पूरी फ़ाइल को पढ़ने से सेड को रोक सकते हैं ... उदा। targln=2; findln=$(sed -rne $targln'{\|// Copyright|=;q}' "$f"); if ((findln==targln));then... लेकिन, ज़ाहिर है, ऊपर और सब कुछ से परे, अच्छी तरह से यह पहले परीक्षण ... पीएस। यह यूनिक्स और लिनक्स में यहाँ पाठ्यक्रम के लिए बराबर है, अपने मूल प्रश्न में ऐसे एक्स्ट्रा पोस्ट करने के लिए, उत्तर के रूप में नहीं ...
पीटर.ऑप

1
कुछ सलाह: चारों ओर कोष्ठक को हटा दें grep, -qविकल्प जोड़ें grep। हमेशा डबल कोट्स को आसपास जोड़ें $f
enzotib

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

गेरहार्ड गप्पीयर का ब्लॉग - हाउटो आवर्ती रूप से फ़ाइल हेडर ऑफ़ सोर्स फ़ाइलों को प्रतिस्थापित करता है

ब्लॉग पोस्ट ने एक tar.gzफाइल संलग्न की है , जिसमें आवश्यक फाइलें हैं।

इसमें एक header.templateफ़ाइल है, जहाँ आप एक कस्टम टिप्पणी लिख सकते हैं, यह कई पंक्तियों को फैला सकती है।

इसमें एक remove_header.awkस्क्रिप्ट है जो मौजूदा हेडर को नए हेडर से बदल देती है।

इसे चलाने के लिए:

find . -name "*.h" -exec ~/rh/replace_header.sh {} \;
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.