Ответ 1
#!/bin/bash
for i in *.cc # or whatever other pattern...
do
if ! grep -q Copyright $i
then
cat copyright.txt $i >$i.new && mv $i.new $i
fi
done
Я ищу инструмент, который в массовом порядке добавит заголовок лицензии в некоторые исходные файлы, некоторые из которых уже имеют заголовок. Есть ли там инструмент, который будет вставлять заголовок, если он еще не присутствует?
Изменить: я намеренно не отмечаю ответ на этот вопрос, так как ответы в основном связаны с окружающей средой и субъективными
#!/bin/bash
for i in *.cc # or whatever other pattern...
do
if ! grep -q Copyright $i
then
cat copyright.txt $i >$i.new && mv $i.new $i
fi
done
Решение Python, измените для своей собственной потребности
Особенности:
-
# updates the copyright information for all .cs files
# usage: call recursive_traversal, with the following parameters
# parent directory, old copyright text content, new copyright text content
import os
excludedir = ["..\\Lib"]
def update_source(filename, oldcopyright, copyright):
utfstr = chr(0xef)+chr(0xbb)+chr(0xbf)
fdata = file(filename,"r+").read()
isUTF = False
if (fdata.startswith(utfstr)):
isUTF = True
fdata = fdata[3:]
if (oldcopyright != None):
if (fdata.startswith(oldcopyright)):
fdata = fdata[len(oldcopyright):]
if not (fdata.startswith(copyright)):
print "updating "+filename
fdata = copyright + fdata
if (isUTF):
file(filename,"w").write(utfstr+fdata)
else:
file(filename,"w").write(fdata)
def recursive_traversal(dir, oldcopyright, copyright):
global excludedir
fns = os.listdir(dir)
print "listing "+dir
for fn in fns:
fullfn = os.path.join(dir,fn)
if (fullfn in excludedir):
continue
if (os.path.isdir(fullfn)):
recursive_traversal(fullfn, oldcopyright, copyright)
else:
if (fullfn.endswith(".cs")):
update_source(fullfn, oldcopyright, copyright)
oldcright = file("oldcr.txt","r+").read()
cright = file("copyrightText.txt","r+").read()
recursive_traversal("..", oldcright, cright)
exit()
Посмотрите copyright-header RubyGem. Он поддерживает файлы с расширениями, заканчивающимися на php, c, h, cpp, hpp, hh, rb, css, js, html. Он также может добавлять и удалять заголовки.
Установите его, набрав "sudo gem install copyright-header
"
После этого можно сделать что-то вроде:
copyright-header --license GPL3 \
--add-path lib/ \
--copyright-holder 'Dude1 <[email protected]>' \
--copyright-holder 'Dude2 <[email protected]>' \
--copyright-software 'Super Duper' \
--copyright-software-description "A program that makes life easier" \
--copyright-year 2012 \
--copyright-year 2012 \
--word-wrap 80 --output-dir ./
Он также поддерживает пользовательские файлы лицензий, используя аргумент --license-file.
Здесь Bash script, который будет делать трюк, если у вас есть заголовок лицензии в файле license.txt:
Файл addlicense.sh:
#!/bin/bash
for x in $*; do
head -$LICENSELEN $x | diff license.txt - || ( ( cat license.txt; echo; cat $x) > /tmp/file;
mv /tmp/file $x )
done
Теперь запустите это в своем исходном каталоге:
export LICENSELEN=`wc -l license.txt | cut -f1 -d ' '`
find . -type f \(-name \*.cpp -o -name \*.h \) -print0 | xargs -0 ./addlicense.sh
Изменить: Если вы используете eclipse, плагин
Я написал простой python script на основе ответа Silver Dragon. Мне нужно было более гибкое решение, поэтому я придумал это. Он позволяет добавлять заголовочный файл ко всем файлам в каталоге, рекурсивно. Вы можете дополнительно добавить регулярное выражение, с которым должны совпадать имена файлов, и регулярное выражение, с которым должны совпадать имена каталогов, и регулярное выражение, которое не должно совпадать с первой строкой в файле. Вы можете использовать этот последний аргумент, чтобы проверить, включен ли заголовок.
Этот script будет автоматически пропускать первую строку в файле, если это начинается с shebang (#!). Это не нарушает другие сценарии, которые полагаются на это. Если вы не желаете этого поведения, вам придется прокомментировать 3 строки в записи.
вот он:
#!/usr/bin/python
"""
This script attempts to add a header to each file in the given directory
The header will be put the line after a Shebang (#!) if present.
If a line starting with a regular expression 'skip' is present as first line or after the shebang it will ignore that file.
If filename is given only files matchign the filename regex will be considered for adding the license to,
by default this is '*'
usage: python addheader.py headerfile directory [filenameregex [dirregex [skip regex]]]
easy example: add header to all files in this directory:
python addheader.py licenseheader.txt .
harder example adding someone as copyrightholder to all python files in a source directory,exept directories named 'includes' where he isn't added yet:
python addheader.py licenseheader.txt src/ ".*\.py" "^((?!includes).)*$" "#Copyright .* Jens Timmerman*"
where licenseheader.txt contains '#Copyright 2012 Jens Timmerman'
"""
import os
import re
import sys
def writeheader(filename,header,skip=None):
"""
write a header to filename,
skip files where first line after optional shebang matches the skip regex
filename should be the name of the file to write to
header should be a list of strings
skip should be a regex
"""
f = open(filename,"r")
inpt =f.readlines()
f.close()
output = []
#comment out the next 3 lines if you don't wish to preserve shebangs
if len(inpt) > 0 and inpt[0].startswith("#!"):
output.append(inpt[0])
inpt = inpt[1:]
if skip and skip.match(inpt[0]): #skip matches, so skip this file
return
output.extend(header) #add the header
for line in inpt:
output.append(line)
try:
f = open(filename,'w')
f.writelines(output)
f.close()
print "added header to %s" %filename
except IOError,err:
print "something went wrong trying to add header to %s: %s" % (filename,err)
def addheader(directory,header,skipreg,filenamereg,dirregex):
"""
recursively adds a header to all files in a dir
arguments: see module docstring
"""
listing = os.listdir(directory)
print "listing: %s " %listing
#for each file/dir in this dir
for i in listing:
#get the full name, this way subsubdirs with the same name don't get ignored
fullfn = os.path.join(directory,i)
if os.path.isdir(fullfn): #if dir, recursively go in
if (dirregex.match(fullfn)):
print "going into %s" % fullfn
addheader(fullfn, header,skipreg,filenamereg,dirregex)
else:
if (filenamereg.match(fullfn)): #if file matches file regex, write the header
writeheader(fullfn, header,skipreg)
def main(arguments=sys.argv):
"""
main function: parses arguments and calls addheader
"""
##argument parsing
if len(arguments) > 6 or len(arguments) < 3:
sys.stderr.write("Usage: %s headerfile directory [filenameregex [dirregex [skip regex]]]\n" \
"Hint: '.*' is a catch all regex\nHint:'^((?!regexp).)*$' negates a regex\n"%sys.argv[0])
sys.exit(1)
skipreg = None
fileregex = ".*"
dirregex = ".*"
if len(arguments) > 5:
skipreg = re.compile(arguments[5])
if len(arguments) > 3:
fileregex = arguments[3]
if len(arguments) > 4:
dirregex = arguments[4]
#compile regex
fileregex = re.compile(fileregex)
dirregex = re.compile(dirregex)
#read in the headerfile just once
headerfile = open(arguments[1])
header = headerfile.readlines()
headerfile.close()
addheader(arguments[2],header,skipreg,fileregex,dirregex)
#call the main method
main()
Для Java http://code.google.com/p/maven-license-plugin/
С уважением
Хорошо, вот простой инструмент для Windows-only, который ищет все файлы указанного вами типа в папке, добавляет текст, который вы хотите к вершине (ваш текст лицензии), и копирует результат в другой каталог (избегая потенциальных перезаписать проблемы). Это также бесплатно. Требуется .Net 4.0.
Я на самом деле автор, поэтому не стесняйтесь запрашивать исправления или новые функции... no promises по расписанию доставки.;)
Дополнительная информация: Инструмент заголовка лицензии в Amazify.com
Проверьте лицензионный-сумматор. Он поддерживает несколько файлов кода (даже настраиваемых) и правильно обрабатывает существующие заголовки. Поставляется уже с шаблонами для наиболее распространенных лицензий с открытым исходным кодом.
Вот один, который я перевернул в PHP для изменения файлов PHP. У меня также была давняя лицензионная информация для удаления, поэтому она сначала заменяет старый текст, затем добавляет новый текст сразу после открытия
<?php
class Licenses
{
protected $paths = array();
protected $oldTxt = '/**
* Old license to delete
*/';
protected $newTxt = '/**
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
*/';
function licensesForDir($path)
{
foreach(glob($path.'/*') as $eachPath)
{
if(is_dir($eachPath))
{
$this->licensesForDir($eachPath);
}
if(preg_match('#\.php#',$eachPath))
{
$this->paths[] = $eachPath;
}
}
}
function exec()
{
$this->licensesForDir('.');
foreach($this->paths as $path)
{
$this->handleFile($path);
}
}
function handleFile($path)
{
$source = file_get_contents($path);
$source = str_replace($this->oldTxt, '', $source);
$source = preg_replace('#\<\?php#',"<?php\n".$this->newTxt,$source,1);
file_put_contents($path,$source);
echo $path."\n";
}
}
$licenses = new Licenses;
$licenses->exec();
Здесь один, который я нашел в списке Apache. Его написано на Ruby и кажется достаточно легким для чтения. Вы даже можете назвать это из грабли для дополнительной особой симпатии.:)
Если вам все еще нужен, есть небольшой инструмент, который я написал, с именем SrcHead. Вы можете найти его на http://www.solvasoft.nl/downloads.html
Если вы используете sbt, https://github.com/Banno/sbt-license-plugin