나는 라이센스/귀속 주석으로 소스 코드 파일을 복잡하게 만드는 것을 싫어하지만 때로는 요구 사항이 될 때도 있습니다. 따라서 수십 개의 소스 코드 파일이 작성되고(하위 디렉터리 트리에 구성됨) 각 파일의 시작 부분에 동일한 여러 줄 주석을 추가해야 합니다.
표준 GNU/Linux 명령줄 도구를 사용하여 이 작업을 수행하는 것이 매우 간단하다고 생각합니다. 비록 제가 이 도구를 진지하게 사용하는 데는 그다지 능숙하지 않기 때문에 양해를 구하고 도움을 요청합니다.
나에게 필요한 것은 모든 theTargetFile.txt
in ./*.txt
(하위 디렉토리의 재귀 포함)을 cat theCommonComment.txt theTargetFile.txt
.
또한 특정 마스크에 맞는 파일을 제외하고 싶습니다. 예를 들어 모든 파일을 고려 *.txt
하되 그대로 두십시오 *.DontTouch.txt
.
find
내 생각에 나에게 정말로 필요한 가장 어려운 부분은 하위 디렉터리를 실행하고, *.txt
파일을 포함하고, 파일을 제외하는 멋진 기반 주문이라고 생각합니다 *.DontTouch.txt
.
답변1
제가 생각할 수 있는 가장 간단한 방법은 GNU를 사용하는 find
것 입니다 bash
.sponge
더 많은 유틸리티:
find dir/with/files -name '*.txt' ! -name '*.DontTouch.txt' -print0 |
while IFS= read -rd '' file; do
echo 'cat path/to/theCommonComment.txt "$file" | sponge "$file"'
done
현재로서는 실제로 아무것도 하지 않고 cat
/ 명령만 인쇄합니다. sponge
필요한 것이 확실하다면 명령 주위에 있는 에코와 작은따옴표를 제거할 수 있습니다.
sponge
또는 find 옵션을 사용하지 않으면 -print0
이 옵션이 모든 시스템에서 작동하지 않을 수 있습니다 .
find dir/with/files -name '*.txt' ! -name '*.DontTouch.txt' -exec sh '
for file; do
tempfile=$(mktemp)
cat path/to/theCommonComment.txt "$file" >"$tempfile"
mv "$tempfile" "$file"
done
' sh {} +
이를 중지할 수 있는 쉬운 방법은 없습니다. 수행할 작업을 인쇄하면 되므로 주의하세요. 주의할 점 - theCommonComment.txt
파일이 재귀 작업을 수행 중인 디렉터리에 없는지 확인하세요(또는 적어도 조회에서 제외되었는지 확인하세요). 그렇지 않으면 일부 파일에 대해 두 개의 헤더가 생성됩니다.
고쳐 쓰다
마지막 생각은 헤더가 파일에 추가되었는지 확인하고 싶을 수도 있다는 것입니다. 이는 새 파일을 추가하고 명령을 다시 실행해야 하는 경우 유용할 수 있습니다. 또한 theCommonComment.txt
검색 경로에 파일을 배치하는 문제 도 해결합니다 . 이 두 가지 솔루션은 다음과 같습니다.
comment_file=path/to/theCommonComment.txt
size=$(wc -c "$comment_file")
find dir/with/files -name '*.txt' ! -name '*.DontTouch.txt' -print0 |
while IFS= read -rd '' file; do
if [ cmp -n "$size" $comment_file" "$file" ]; do
echo 'cat "$comment_file" "$file" | sponge "$file"'
fi
done
export comment_file=path/to/theCommonComment.txt
export size=$(wc -c "$comment_file")
find dir/with/files -name '*.txt' ! -name '*.DontTouch.txt' -exec sh '
for file; do
if [ cmp -n "$size" $comment_file" "$file" ]; do
tempfile=$(mktemp)
cat "$comment_file" "$file" >"$tempfile"
mv "$tempfile" "$file"
fi
done
' sh {} +
답변2
GNU/모든 것에서 첫 번째 줄 뒤에 삽입하려면:
find -name '*.txt' ! -name '*thispattern*' ! -name '*thatpattern*' \
-exec sed -si '1r TheLicense.txt' '{}' +
이전에 파일을 삽입하는 가장 간단한 방법은 약간 느리고 약간 혼란스러운 것입니다.
find -name '*.txt' ! -name '*thispattern*' ! -name '*thatpattern*' \
-exec sed -si '1{h;s,.*,cat TheLicense.txt,ep;g}' '{}' +
답변3
그리고 zsh
:
zmodload zsh/mapfile
setopt extendedglob # best in ~/.zshrc
for f (Dir/**/(^*DontTouch).txt(N.))
mapfile[$f]=$mapfile[theCommonComment.txt]$mapfile[$f]
답변4
이 솔루션은 bash, find, tac 및 sed를 사용합니다.
다음 스크립트를 파일에 복사하고 파일을 실행 가능하게 만듭니다.chmod +x script
그런 다음 다음과 같이 사용하십시오.
./script <DIR> <HEADERFILE>
어디
<DIR> The directory containing files ( or directory containing files..)
<HEADERFILE> The file to add on top of each file
스크립트는 다음과 같습니다.
#!/bin/bash
# inset a file content at the beginning of each matching files
DIR=$1
HEADER_FILE=$2
#the matching files will be ignored
IGNORE_FILE="*.DontTouch.txt"
insertHeader(){
local targetfile=$1
local headerfile=$2
echo "$targetfile"
while read line
do
# echo $line
sed -i "$targetfile" -e "1i$line\ "
done< <(tac "$headerfile")
}
export -f insertHeader
find "$DIR" -type f -name "*.txt" ! -name "$IGNORE_FILE" -exec bash -c "insertHeader {} $HEADER_FILE" \;