
.dot 파일(.dot 디렉터리 아님)을 디렉터리에 복사하고 싶습니다. 이렇게 하려면 운영 체제(MacOS)에서 사용자 비밀번호를 입력해야 합니다. 저는 이 작업을 수행하는 함수를 만들었고 이를 다음과 같은 더 큰 백업 스크립트에 통합하려고 합니다.
#!/bin/zsh
source ~/.zshrc
set -o errexit
set -o nounset
set -o pipefail
copy_dotfiles()
{
MAIN_PATH="/Users/user01/"
DOTFILE_DIR="${MAIN_PATH}Documents/dot_files"
echo $DOTFILE_DIR
mkdir $DOTFILE_DIR
for f in $MAIN_PATH.[!.]*; do
if [[ -f $f ]]; then
echo "$f" is a file
DOTFILE=`echo $f | sed 's/\/Users\/user01\///g'`
echo "$DOTFILE" is a file
cp $f ${DOTFILE_DIR}/${DOTFILE} || exit 1
elif [[ -d $f ]]; then
echo "$f" is a dir
continue
else
echo "$f is not valid"
exit 1
fi
done
}
sudo copy_dotfiles || exit 1
그러나 스크립트를 실행하면 다음과 같은 결과가 나타납니다.
sudo: copy_dotfiles: command not found
답변1
sudo
쉘 함수가 아닙니다. 실행 파일을 실행하는 별도의 실행 파일입니다. :)
따라서 쉘 기능을 실행할 수 없습니다. 그래도 쉘 스크립트를 실행할 수 있습니다! 따라서 작동하도록 하려면 sudo
이 스크립트에서 이를 생략하고 sudo를 통해 전체 스크립트를 실행하십시오.
너정말source ~/.zshrc
어쨌든 삭제해야 하지만특히스크립트를 루트로 실행할 때.
답변2
이 코드에 대한 인라인 주석:
#!/bin/zsh source ~/.zshrc
호출하는 사용자의 대화형 셸 사용자 정의 파일을 스크립트로 가져오려는 이유는 무엇입니까? 이것은 말이 되지 않습니다.
set -o errexit
설정했지만 취소된 상태에서 효과를 errexit
사용하려고 시도했습니다 .somefunction || ...
errexit
set -o nounset set -o pipefail
set -o errexit -o nounset -o pipefail
POSIX 셸에서 이 작업을 수행 할 수 있는 것은 아닙니다 .setopt errexit nounset pipefail
copy_dotfiles() { MAIN_PATH="/Users/user01/" DOTFILE_DIR="${MAIN_PATH}Documents/dot_files"
이름이 모두 대문자인 변수는 일반적으로 환경 변수나 glob 범위의 변수에 사용됩니다. 함수에서 전역 변수를 고정된 값으로 설정하는 것이 이상해 보입니다.
copy_dotfiles() { # Arg: username
local target_dir=~$1/Documents/dot_files
사용자 이름을 매개변수로 사용 copy_dotfiles
하고 홈 디렉터리에 대상 디렉터리의 로컬 변수를 설정하는 것이 더 합리적입니다.
매개변수를 대상으로 하지 않는 함수를 정의하는 것은 의미가 없습니다.
echo $DOTFILE_DIR
인쇄하기 전에 매개변수를 주의 깊게 echo
변환하십시오. 사용하는 것이 가장 좋습니다: print -r -- $DOTFILE_DIR
또는printf '%s\n' $DOTFILE_DIR
mkdir $DOTFILE_DIR
이를 실행하면 대상 사용자 대신 해당 사용자를 사용하여 새 디렉터리가 생성됩니다 root
. root
함수의 종료 상태를 확인하지 않고 mkdir
함수 errexit
의 종료 상태를 처리하는 경우 해당 함수가 취소되므로 나머지 코드가 mkdir
실패할 수 있습니다. 예를 들어 사용자가 민감한 시스템에 대한 심볼릭 링크를 생성했거나 ~/Documents/dot_files
민감한 파일에 대한 심볼릭 링크가 있는 파일이 포함된 디렉터리를 만든 경우 심각한 결과를 초래할 수 있습니다 /etc/shadow
./root/.bashrc
또한, 로 끝나는 경우에는 cmd $anything_dynamic
원칙적 cmd -- $anything_dynamic
으로 .$anything_dynamic
-
for f in $MAIN_PATH.[!.]*; do
$dir/file-within
변수 값에 후행 문자열을 추가 하고 do를 수행하는 대신 pathname/dir 변수를 디렉터리 경로로 정의하고 이를 사용하는 것이 더 일반적입니다 ./
${dir}file-within
.
또한 zsh glob에는 nor 가 포함되지 않습니다 ..
. zsh에서는 파일을 제외 하고 제외 하더라도 부정 설정 ^
보다 우선합니다 .!
.[!.]*
.
..
..file
N
빈 목록을 허용하고 지역 변수를 선언하기 위해 glob 한정자를 사용할 수도 있습니다 f
.
local f
for f in $source_dir/.*(N); do
if [[ -f $f ]]; then echo "$f" is a file
더 좋아해요 print -r -- $f is a regular file or symlink to regular file
.
또한 zsh
glob은 유형별로 파일을 선택할 수 있으므로 여기서 반복할 필요가 없습니다 [[...]]
.
DOTFILE=`echo $f | sed 's/\/Users\/user01\///g'` echo "$DOTFILE" is a file cp $f ${DOTFILE_DIR}/${DOTFILE} || exit 1
줄 기반이고 파일 경로가 여러 줄로 구성될 수 있으므로 다른 텍스트 유틸리티를 사용하여 파일 경로를 수정하는 sed
것은 일반적으로 실수입니다 . 텍스트 교체 연산자( ksh 및 csh 포함)가 내장되어 있으며 경로의 꼬리를 가져오지만 여기서는 둘 다 수행하므로 교체를 수행할 필요가 없습니다.sed
zsh
${var/pattern/replacement}
$var:s/string/replacement/
$var:t
cp
에게 복사그리고에게 복사.
cp -- $f $target_dir/
$f
해당 경로가 저장된 디렉토리에 복사됩니다 $target_dir
.
그러나 루트로 실행하면 위험할 수 있습니다.
elif [[ -d $f ]]; then echo "$f" is a dir continue else echo "$f is not valid" exit 1 fi done } sudo copy_dotfiles || exit 1
sudo
실행할 명령 파일의 이름이나 경로를 사용하는 외부 명령입니다. 쉘이나 다른 프로그래밍 언어에서는 함수 이름을 얻을 수 없습니다.
쉘을 실행하도록 지시할 수 있으며, 쉘은 다음을 사용할 수 있는 함수를 정의하고 호출합니다.
exec sudo zsh -o errexit -o nounset -o pipefail -c '
'"$(typeset -f -- copy_dotfile)"'
"$0" "$@"' copy_dotfile "$@"
하지만 여기에서는 전체 스크립트가 바로 해당 함수이므로 루트로 호출할 수도 있고, 스크립트가 슈퍼유저가 아닌 경우 루트로 다시 실행해 볼 수도 있습니다.
#! /bin/zsh -
set -o nounset
# reexecute as root if effecive uid is not 0 (not privileged).
(( EUID == 0 )) || exec sudo -u root -- "$0" "$@"
user=${1?}
ERRNO=0 USERNAME=$user # drop privileges by switching all uids and gids
# to those of the target user
(( ERRNO )) && exit 1 # abort if we couldn't drop privileges
# cd to the source directory
cd -P -- ~$user || exit
# hidden regular (.) files.
dotfiles=( .*(N.) )
destdir=Documents/dot_files
mkdir -p -- $destdir || exit
if (( $#dotfiles )) exec cp -pP -- $dotfiles $destdir/
(테스트되지 않음)