Я пытаюсь добавить заголовок лицензии ко всем заголовочным файлам и исходным файлам в каталоге проекта, используя цикл for. Это не работает, есть ли другой подход sed
?
Я пытаюсь добавить заголовок лицензии ко всем заголовочным файлам и исходным файлам в каталоге проекта, используя цикл for. Это не работает, есть ли другой подход sed
?
Ответы:
Это более или менее просто расширенный комментарий к ответу Даниэля Серодио . Я начал писать это как комментарий, но он быстро стал слишком большим ...
Для того чтобы bash glob был рекурсивным, требуется 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
from package 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 {} \;