나는 채점자이고 나에게 제출된 파일은 학생의 이름을 딴 폴더에 저장되며, 이 폴더 자체는 내 Linux 공유의 특정 폴더에 있습니다.
현재는 각 소스 파일을 살펴보고 각 파일 상단에 수동으로 설명을 추가하여 인쇄할 때 어떤 파일이 어떤 학생에게 속하는지 알 수 있도록 합니다.
제가 하고 싶은 일은 과제 폴더를 재귀적으로 탐색하고 각 학생 폴더로 드롭다운할 때 학생 디렉터리 이름을 사용하여 해당 폴더의 각 파일 상단에 댓글을 추가하여 댓글 콘텐츠에 어떤 항목을 추가할지 파악하는 것입니다.
이것파일 상단에 댓글을 추가한다는 점에서는 비슷한 것 같은데, 학생 폴더별로 댓글을 넣을 때 어떻게 동적으로 댓글을 생성할 수 있는지 잘 모르겠습니다.
최신 업데이트
여전히 작동하지 않지만 여기에 제가 변경한 사항이 있으므로 찾을 필요가 없습니다.
몇 가지 사항을 변경했습니다.
- printf 문의 작은따옴표는
'
inisn't
이 일찍 종료되기 때문에 이제 큰따옴표가 됩니다. -writable
쓰기 가능 으로 변경하면-perm 664
오류가 발생하고 변경하려는 모든 파일은 업로드 시 644로 설정됩니다. 이보다 더 좋은 방법을 아시면 알려주세요.- 이제 exec를 올바르게 이해하면 $1이 선언되지 않았으므로(
echo $1
exec 매개변수를 추가하면 이를 확인함)_filepath={}
exec 매개변수 끝에 이를 추가하고 제거했습니다.{}
- 초기화
_dirname
됨_filepath
- 디렉터리 이름을 분리하기 위해 정규식을 사용하는 두 줄에서는 큰따옴표가 닫히지 않습니다. _dirname은 이제 디렉토리 이름만 성공적으로 저장합니다.
- 이제 ed에게 전화하세요
_filepath
이것이 작동하지 않는 이유는 ed를 호출하는 줄의 작은따옴표가 exec 매개변수를 닫기 때문이라고 확신합니다.
현재 코드:
student_head_action() {
# We can't use parameter expansion on $PWD because of recursion
local _dirname="${1%/*}"
_dirname="${_dirname##*/}"
[[ -d $1 ]] && return 0
if ! [[ -w $1 && -f $1 ]]; then
printf '%s\n' "$1 does not exist or is not writeable, skipping"
return 1
fi
ed -s "$1" <<< $'0a\n'"//${_dirname}"$'\n.\n,s/\r//g\nw'
}
student_head() {
local _file
if (( $# )); then
for _file; do
student_head_action "${_file}" || _retval=1
done
else
if shopt -qs globstar; then
for _file in **/*; do
student_head_action "${_file}" || _retval=1
done
shopt -u globstar
else
printf "%s\n" "Globstar isn't available, attempting to use GNU find ..."
find . -type f -perm 644 -exec bash -c '
_filepath={}
_dirname=$_filepath
_dirname="${_dirname%/*}"
_dirname="${_dirname##*/}"
echo $_dirname
ed -s "$_filepath" <<< '"$'0a\n'"'"//${_dirname}"'"$'\n.\n,s/\r//g\nw'" \;
fi
fi
return "${_retvalue-0}"
답변1
student_head
폴더 내에서 실행하여 폴더 이름을 폴더 및 하위 디렉터리 내의 쓰기 가능한 파일에 헤더로 자동 추가할 수 있습니다 .
student_head_action() {
# We can't use parameter expansion on $PWD because of recursion
local _dirname="${1%/*}"
_dirname="${_dirname##*/}"
[[ -d $1 ]] && return 0
if ! [[ -w $1 && -f $1 ]]; then
printf '%s\n' "$1 does not exist or is not writeable, skipping"
return 1
fi
bash -c "ed -s {} <<< $'0a\n'"# Student: ${_dirname}"$'\n.\n,s/\r//g\nw'"
}
student_head() {
local _file
if (( $# )); then
for _file; do
student_head_action "${_file}" || _retval=1
done
else
if shopt -s globstar > /dev/null 2>&1; then
for _file in **/*; do
student_head_action "${_file}" || _retval=1
done
shopt -u globstar
else
printf '%s\n' 'Globstar isn't available, attempting to use GNU find...'
find . -type f -writable -exec bash -c '
_dirname="${1%/*}\
_dirname="${_dirname##*/}\
ed -s "$1" <<< '"$'0a\n'"'"# Student: ${_dirname}"'"$'\n.\n,s/\r//g\nw'" {} \;
fi
fi
return "${_retval-0}"
}
사용자가 사용하기를 ~/.bashrc
원하는 경우 .student_head
bash
student_head
두 가지 방법으로 호출할 수 있습니다.
- 분쟁이 없습니다. 이 모드에서는 현재 디렉터리와 해당 하위 디렉터리에 있는 모든 쓰기 가능한 파일 앞에 헤더가 추가됩니다.
- 파일 이름을 인수로 사용합니다. 이 모드에서는 매개변수에 나열된 파일에만 헤더가 추가됩니다.
인수의 파일이 존재하지 않으면 student_head
종료 상태 1이 반환됩니다.
이 스크립트 globstar
는 bash>=4.0
.
답변2
find
와 를 결합한 솔루션입니다 ed
.
add_header() {
declare regex IFS='|'
(( $# )) && regex="^($*)$" || regex=""
find "$PWD" -type f -exec bash -c '
( exec grep -E -qs -e "$0" <<<"${1##*/}" ) || exit
_dirname="${1%/*}"
_dirname="${_dirname##*/}"
exec ed -s "${1}" <<EOF
0a
# Student: ${_dirname}
.
wq
EOF
' "${regex:-.+}" '{}' \;
return 0
}
add_header # all files in current directory recursively
add_header file1 file2 file3 # only named files in current directory recursively