94

我正在寻找一种工具,它可以批量向一些源文件添加许可证头,其中一些源文件已经有了头文件。是否有一个工具可以插入一个标题,如果它不存在的话?

编辑:我故意不标记这个问题的答案,因为答案基本上都是特定于环境和主观的

4

12 回答 12

69
#!/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
于 2008-09-30T03:48:48.540 回答
16

Python 2 解决方案,根据自己的需要进行修改

特征:

  • 处理 UTF 标头(对大多数 IDE 很重要)
  • 递归更新目标目录中传递给定掩码的所有文件(修改 .endswith 参数以获取您的语言的文件掩码(.c、.java、..etc)
  • 覆盖以前的版权文本的能力(提供旧的版权参数来做到这一点)
  • 可选地省略excludedir数组中给定的目录
# 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()
于 2008-09-30T03:44:46.817 回答
16

假设您在文件 license.txt 中有许可标头,下面是一个可以解决问题的 Bash 脚本:

文件 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  
于 2008-09-30T03:56:06.773 回答
16

查看版权标题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 <dude1@host.com>' \
  --copyright-holder 'Dude2 <dude2@host.com>' \
  --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 参数的自定义许可证文件。

于 2012-07-17T22:05:05.133 回答
13

编辑:如果您使用的是 eclipse,则有一个插件

我根据银龙的回复写了一个简单的python脚本。我需要一个更灵活的解决方案,所以我想出了这个。它允许您递归地将头文件添加到目录中的所有文件。您可以选择添加文件名应匹配的正则表达式,目录名称应匹配的正则表达式和文件中第一行不应匹配的正则表达式。您可以使用最后一个参数来检查标头是否已包含在内。

如果文件以 shebang (#!) 开头,此脚本将自动跳过文件中的第一行。这不会破坏依赖于此的其他脚本。如果您不希望这种行为,您必须在 writeheader 中注释掉 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()
于 2012-03-12T17:11:03.963 回答
12

对于 Java,您可以使用 Maven 的许可证插件:http ://code.google.com/p/maven-license-plugin/

于 2008-10-01T02:07:49.757 回答
11

好的,这是一个简单的仅限 Windows 的 UI 工具,它在文件夹中搜索您指定类型的所有文件,将您想要的文本添加到顶部(您的许可证文本),并将结果复制到另一个目录(避免潜在的覆盖问题) . 它也是免费的。需要 .Net 4.0。

我实际上是作者,所以请随时请求修复或新功能……尽管对交付时间表没有承诺。;)

更多信息:Amazify.com上的许可证头工具

于 2011-10-29T19:39:51.477 回答
5

查看许可证添加器。它支持多个代码文件(甚至是自定义的)并正确处理现有的标头。已经带有最常见的开源许可证的模板。

于 2012-09-02T08:49:06.577 回答
4

这是我使用 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();
于 2013-04-21T03:15:40.067 回答
3

这是我在 Apache 列表中找到的一个。它是用 Ruby 编写的,看起来很容易阅读。你甚至应该能够从 rake 中调用它以获得额外的特殊好处。:)

于 2009-01-31T11:59:25.417 回答
1

如果你还需要一个,我写了一个小工具,叫做SrcHead。您可以在http://www.solvasoft.nl/downloads.html找到它

于 2009-03-20T20:03:27.463 回答
1

如果您使用的是 sbt,则有https://github.com/Banno/sbt-license-plugin

于 2013-05-28T21:58:25.480 回答