
私は採点者であり、私に提出されたファイルは学生の名前が付けられたフォルダに保存され、このフォルダ自体は私のLinux共有の特定のフォルダにあります。
現在では、各ソースファイルを調べて、各ファイルの上部に手動で説明を追加して、印刷するときにどのファイルがどの生徒に属しているかを知ることができます。
私がやりたいことは、課題フォルダを再帰的に移動し、各生徒フォルダにドロップダウンするときに生徒ディレクトリ名を使用して、そのフォルダ内の各ファイルの上部にコメントを追加して、コメントコンテンツにどの項目を追加するかを把握することです。
これファイルの一番上にコメントを追加するという点では似ていますが、生徒フォルダごとにコメントを入れるときに動的にコメントを生成する方法はわかりません。
最新のアップデート
それでも動作しませんが、ここに私が変更したものがあるので、見つける必要はありません。
いくつか変更しました。
- printfステートメントの一重引用符は
'
inisn't
が早く終了するため、二重引用符になります。 -writable
書き込み可能に変更すると-perm 664
エラーが発生し、変更したいファイルはすべてアップロード時に644に設定されます。これより良い方法をご存知であれば教えてください。- execを正しく理解しても$ 1が宣言されていないので(
echo $1
execパラメータを追加すると確認します)、_filepath={}
execパラメータの末尾にそれを追加して削除しました。{}
- 初期化
_dirname
済み_filepath
- ディレクトリ名を区切るために正規表現を使用する2行では、二重引用符は閉じられません。 _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
2つの方法で呼び出すことができます。
- 紛争はありません。このモードでは、現在のディレクトリとそのサブディレクトリにあるすべての書き込み可能ファイルの前にヘッダーが追加されます。
- ファイル名を引数として使用します。このモードでは、パラメーターにリストされているファイルにのみヘッダーが追加されます。
引数のファイルが存在しない場合、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