Jak rekursywnie dodawać nagłówek licencji dla wszystkich plików .h i .cpp w katalogu


19

Próbuję dodać nagłówek licencji do wszystkich plików nagłówka i plików źródłowych w katalogu projektu za pomocą pętli for. To nie działa, czy używasz innego podejścia sed?


1
Bardzo podobny przypadek: unix.stackexchange.com/questions/20577/…
pbm

Odpowiedzi:


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

1
Należy wspomnieć, że musisz włączyć globstarbash, aby to zadziałało.
Chris Down,

I że potrzebujesz bash> 4.0 (np. Mac OS X i RedHat 5 są nadal w wersji 3.X)
Matteo

11

To mniej więcej rozszerzony komentarz do odpowiedzi Daniela Serodio . Zacząłem pisać jako komentarz, ale szybko stał się zbyt duży ...

Aby bash glob był rekurencyjny, wymaga tego shopt -s globstar. Musisz włączyć globstar, w przeciwnym razie **nie działa. Opcja powłoki globstar została wprowadzona do wersji 4 bash.

Aby uniknąć przetwarzania katalogu, takiego jak my.cpp/: użyj testu [[ -f $f ]]... Gdy test jest w nawiasach kwadratowych, zmienne nie muszą być cudzysłowione.

Można również rozważyć możliwość braku dopasowania pasujących plików shopt -s nullglob, co pozwala na rozwinięcie wzorców, które nie pasują do żadnego pliku, do łańcucha zerowego, a nie do siebie.

Aby obsługiwać wiele wzorów, można łańcucha wzorców glob: **/*.cpp **/*.h, ale może preferrably, gdy opcja powłoki extglob jest on za pośrednictwem shopt -s extglob, można użyć takich konstruktów, takich jak **/*.@(cpp|h)co pozwala uniknąć wielu przechodzi nad systemem plików; raz dla każdego wzoru.

Jeśli chcesz .fileszostać uwzględniony, użyj .*.cppitp. Lub użyjshopt -s dotglob

Aby bezpiecznie obsłużyć modyfikowanie pliku, który jest przesyłany potokiem, użyj spongez pakietu moreutils(oszczędza to konieczności tworzenia własnego pliku tymczasowego)


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

Znacznie bardziej kompletna i pouczająca odpowiedź niż druga, +1
n0pe

+1, ale [[może z wdziękiem obsłużyć wartość zerową $f.
enzotib

@enzotib. dzięki. Nie jestem pewien, skąd wziął się ten pomysł. Musiało to unset x; [ -f $x ] && echo exists
wynikać

Ponieważ wersja 4 bash nie jest jeszcze w głównym nurcie, zastąpiłbym **/*.@(cpp|h)$( find . -name "*.h" -name "*.cpp")
Matteo

3

Dziękuję @fred, @maxmackie, @enzotib.

Czy możesz sprawdzić procedurę, którą zastosowałem.

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

w przeciwnym razie nagłówek licencji zostanie skopiowany wiele razy.

Proszę zasugerować mi wzorzec, który powinien przejść przez wszystkie nagłówki i źródła w katalogu projektu i podkatalogach.

Nie mogłem w pełni zrozumieć, co sugeruje @fred.


Ogólnie twój kod wygląda dobrze. Chciałbym bardziej szczegółowo określić dokładną lokalizację „praw autorskich”, np. podaj numer linii i pozycję w tej linii. Możesz uniemożliwić sedowi odczytanie całego pliku, wychodząc z linii, w której spodziewasz się znaleźć „Copyright” ... np. targln=2; findln=$(sed -rne $targln'{\|// Copyright|=;q}' "$f"); if ((findln==targln));then... ale oczywiście ponad wszystko, najpierw dokładnie go przetestuj ... PS. Oczywiście w Unix i Linuxie kurs jest taki, żeby zamieszczać takie dodatki w oryginalnym pytaniu, a nie jako odpowiedź ...
Peter.O

1
Kilka porad: usuń nawiasy grep, dodaj -qopcję do grep. Zawsze dodawaj podwójne cudzysłowy $f.
enzotib

1
Cytaty są niezbędne, w przeciwnym razie zostaniesz ugryziony przez dzielenie słów. Podstawową zasadą jest cytowanie każdego rozwinięcia, chyba że wiesz, że dzielenie słów lub inna interpretacja nie będą wykonywane przez powłokę.
Chris Down,

3

Możesz to zrobić za pomocą exlub edjeśli wolisz (nie powinieneś tego robić sedzgodnie z życzeniem, sedjest przeznaczony do edycji strumieni, -ito zły pomysł z różnych powodów):

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

Dlaczego jest sed -ito zły pomysł?
Daniel Serodio

@DanielSerodio Domyślnie sed -iłamie dowiązania symboliczne i dowiązania twarde, co powoduje nieoczekiwane zachowanie. W najlepszym wypadku jest to nieintuicyjne, w gorszym jest aktywnie szkodliwe.
Chris Down,

2

Jeśli masz header_filepożądaną zawartość:

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

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.