디렉토리의 모든 .h 및 .cpp 파일에 대해 라이센스 헤더를 재귀 적으로 추가하는 방법


19

for 루프를 사용하여 프로젝트 디렉토리의 모든 헤더 파일과 소스 파일에 라이센스 헤더를 추가하려고합니다. 이것은 작동하지 않습니다. 사용하는 다른 방법이 sed있습니까?


1
매우 비슷한 경우 : unix.stackexchange.com/questions/20577/…
pbm

답변:


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

1
이것이 globstar작동하려면 bash에서 켜야한다고 언급해야합니다 .
Chris Down

그리고 bash> 4.0이 필요합니다 (예 : Mac OS X 및 RedHat 5는 여전히 3.X입니다)
Matteo

11

이것은 Daniel Serodio의 대답 에 대한 확장 된 주석입니다 . 주석으로 작성하기 시작했지만 너무 빨리 커졌습니다 ...

bash glob가 재귀 적이어야하려면 shopt -s globstar. globstar를 활성화해야합니다 **. 그렇지 않으면 작동하지 않습니다. globstar 쉘 옵션은 bash 버전 4에 도입되었습니다.

과 같은 디렉토리를 처리하지 않으려면 my.cpp/test [[ -f $f ]]...를 사용하십시오 . 테스트가 큰 대괄호 안에 있으면 변수를 큰 따옴표로 묶을 필요가 없습니다.

또한 파일을 사용 shopt -s nullglob하지 않는 패턴을 자체가 아닌 null 문자열로 확장 할 수있는 을 사용하여 일치하는 파일이 없을 가능성을 고려할 수 있습니다 .

여러 패턴을 처리하기 위해, 당신은 글로브 패턴을 체인 수 **/*.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

+1
n0pe

+1이지만 [[null을 정상적으로 처리 할 수 ​​있습니다 $f.
enzotib

@enzotib. 감사. 나는 그 아이디어를 얻었는지 확실하지 않습니다. 그것은 (하지 않습니다) 방법 단일 대괄호 작품에서 예를 들면되어 있어야합니다 unset x; [ -f $x ] && echo exists (고정) "존재"보고서
Peter.O

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. 유닉스와 리눅스 에서 당신의 원래 질문에 답이 아닌 추가 내용 을 게시하는 것은 여기에
필적입니다

1
몇 가지 조언 : 괄호를 제거 grep하고에 -q옵션을 추가하십시오 grep. 주위에 항상 큰 따옴표를 추가하십시오 $f.
enzotib

1
따옴표는 매우 중요합니다. 그렇지 않으면 단어 분리로 물릴 수 있습니다. 기본적으로 셸에서 단어 분리 또는 기타 해석을 수행하지 않을 경우를 제외하고는 모든 확장을 인용하십시오.
Chris Down

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

@DanielSerodio 기본적으로 sed -i심볼릭 링크와 하드 링크를 끊어 예기치 않은 동작이 발생합니다. 기껏해야 비 직관적이며, 더 나쁘면 적극적으로 해 롭습니다.
Chris Down

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 {} \;
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.