如何为目录中的所有.h和.cpp文件递归添加许可证标头


19

我正在尝试使用for循环将许可证标头添加到项目目录中的所有标头文件和源文件中。这是行不通的,是否还有其他使用方法sed



Answers:


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

1
应该提到的是,您需要打开globstarbash才能工作。
克里斯·

并且您需要bash> 4.0(例如Mac OS X和RedHat 5仍在3.X上)
Matteo

11

这或多或少只是对Daniel Serodio的回答的扩展评论。我开始写它作为评论,但很快就变得太大了。

为了使bash全局递归,需要shopt -s globstar。您必须启用globstar,否则**将不起作用。globstar shell选项已引入bash的版本4中。

为避免处理目录,例如my.cpp/,请使用test [[ -f $f ]]...当测试位于双方括号中时,变量不需要用双引号引起来。

您还可以使用来考虑是否存在不匹配文件的可能性shopt -s nullglob,它允许不匹配文件的模式扩展为空字符串,而不是自身。

为了处理多个模式,你可以链中的glob模式:**/*.cpp **/*.h,但也许preferrably,当外壳选项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

比其他人更完整,更有意义的答案,+ 1
n0pe 2011年

+1,但[[可以正常处理null $f
enzotib

@enzotib。谢谢。我不确定我是从这个想法得到的。一定是来自单个方括号的工作原理(不是)……例如,unset x; [ -f $x ] && echo exists 报告“存在”……(固定)
Peter.O 2011年

由于bash的第4版不是主流,所以我**/*.@(cpp|h)$( find . -name "*.h" -name "*.cpp")
Matteo

3

谢谢@ 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的建议。


通常,您的代码看起来还可以。我将更具体地说明例如“版权”的确切位置。指定行号和该行的位置。您可以通过在希望查找“版权”的行上退出来防止sed读取整个文件。 targln=2; findln=$(sed -rne $targln'{\|// Copyright|=;q}' "$f"); if ((findln==targln));then...但是,当然,除了其他所有方面之外,首先要对其进行彻底测试... PS。在Unix和Linux上的课程中,将这样的额外内容张贴在您的原始问题中,而不是作为答案,是
同等的

1
一些建议:删除括号,在grep中添加-q选项grep。始终在前后加上双引号$f
enzotib

1
报价很重要,否则您可能会被单词拆分所咬。作为基本规则,除非您知道shell不会执行分词或其他解释,否则请引述每个扩展。
克里斯·

3

你可以做到这一点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个坏主意?
Daniel Serodio '17

@DanielSerodio默认情况下,sed -i会断开符号链接和硬链接,从而导致意外行为。充其量它是非直觉的,更糟的是它是有害的。
克里斯·

2

如果您有header_file所需的内容:

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

0

Gerhard Gappmeier的博客-如何递归替换源文件的文件头

博客文章附有一个 tar.gz文件,其中包含所需的文件。

它有一个 header.template文件,您可以在其中编写自定义注释,它可以跨越多行。

它有一个 remove_header.awk脚本,可以用新的标题替换现有的标题。

为了运行它:

find . -name "*.h" -exec ~/rh/replace_header.sh {} \;
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.