Я намагаюся додати заголовок ліцензії до всіх файлів заголовків та вихідних файлів у каталозі проекту, використовуючи цикл for. Це не працює, чи є якийсь інший підхід sed?
Я намагаюся додати заголовок ліцензії до всіх файлів заголовків та вихідних файлів у каталозі проекту, використовуючи цикл for. Це не працює, чи є якийсь інший підхід sed?
Відповіді:
Це більш-менш просто розширений коментар до відповіді Даніеля Серодіо . Я почав писати це як коментар, але він швидко став занадто великим ...
Щоб глобус-баш був рекурсивним, це потрібно shopt -s globstar. Потрібно включити globstar, інакше **не працює. Варіант оболонки globstar був представлений до версії 4 bash.
Щоб уникнути обробки такої директорії, як 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
[[може витончено обробити нуль $f.
unset x; [ -f $x ] && echo exists звіти "існує" ... (виправлено)
**/*.@(cpp|h)з$( find . -name "*.h" -name "*.cpp")
Дякую @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... але, звичайно, вище і далі всього іншого, ретельно перевірити його спочатку ... PS. Це курс на курсі тут, в Unix & Linux, щоб розмістити такі додатки в оригінальному запитанні, а не як відповідь ...
grep, додайте -qпараметр до grep. Завжди додайте подвійні лапки $f.
Ви можете це зробити за допомогою 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погана ідея?
sed -iрозриває символьні посилання та жорсткі посилання, що призводить до несподіваної поведінки. У кращому випадку він не інтуїтивно зрозумілий, в гіршому - активно шкідливий.
#!/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
Блог Герхарда Гаппмейера - як рекурсивно замінити заголовки файлів вихідних файлів
До публікації блогу додається tar.gzфайл, що містить необхідні файли.
У ньому є header.templateфайл, куди можна написати спеціальний коментар, він може охоплювати кілька рядків.
У ньому є remove_header.awkсценарій, який замінює існуючі заголовки новим заголовком.
Для того, щоб запустити його:
find . -name "*.h" -exec ~/rh/replace_header.sh {} \;