![사용자(와일드카드) 홈 디렉터리에 파일을 복사하는 Bash 스크립트](https://linux55.com/image/129094/%EC%82%AC%EC%9A%A9%EC%9E%90(%EC%99%80%EC%9D%BC%EB%93%9C%EC%B9%B4%EB%93%9C)%20%ED%99%88%20%EB%94%94%EB%A0%89%ED%84%B0%EB%A6%AC%EC%97%90%20%ED%8C%8C%EC%9D%BC%EC%9D%84%20%EB%B3%B5%EC%82%AC%ED%95%98%EB%8A%94%20Bash%20%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8.png)
/root/nbu/file1.sh
사용자의 ID가 짝수인 경우 각 사용자의 홈 디렉터리에 복사해야 합니다.
다음 스크립트를 실행해 보세요.
#!/bin/bash
cat /etc/passwd | while read LINE
do
username=$(awk -v var="$LINE" -F: '{
if ($3 % 2 == 0)
print $1
}')
cp /root/nbu/file1.sh ~"$username"
done
그러나 그것은 아무것도 하지 않습니다. 명령을 에코 cp /root/nbu/file1.sh ~"$username"
하고 스크립트에서 직접 실행하면 작동합니다.
~
bash 스크립트에서 문제가 확장되는 것 같지만 이 문제를 해결하는 방법을 잘 모르겠습니다.
미리 감사드립니다.
답변1
사용자 이름 부분이 인용된 경우 물결표 확장은 효과가 없습니다.
$ echo ~root ~"root"
/root ~root
(어쨌든 변수 확장 전에 발생합니다.)
하지만 passwd
쉘에서 읽었으므로 전체 내용을 실행해 보는 것은 어떨까요?
#!/bin/bash
getent passwd | while IFS=: read -r user pass uid gid gecos home shell; do
if (( uid % 2 == 0 )); then
echo "uid $uid of user '$user' is even and their home is '$home'";
fi;
done
시스템에 가 있으면 직접 사용하는 getent
것보다 사용하는 것이 좋습니다 /etc/passwd
.
반면에 아무것도 수행하는 데 사용자 이름이 실제로 필요하지 않은 것 같으므로 awk
스크립트 출력 만 있으면 됩니다.목차( $6
) 그와 반대로요.
답변2
그 이유는변수 확장 전에 물결표 확장이 발생합니다.:
확장 순서는 중괄호 확장, 인수 및 변수 확장, 산술 확장, 명령 대체(왼쪽에서 오른쪽으로 수행)입니다.
echo
계산 결과것 같다맞습니다. 재평가하면 작동하지만 스크립트의 경우 다르게 수행해야 합니다. 아마도:
# ...
homedir=$(getent passwd "$username" | cut -d: -f6)
cp /root/nbu/file1.sh "$homedir"
# ...
답변3
당신은 매우 재주가 있어 보여서 스크립트를 제공하지는 않겠습니다. 그러나 다음은 몇 가지 팁입니다.
awk
당신은 그것을 잘못 사용하고 있습니다 . 이 시도:awk -F: -v uid_min=${UID_MIN:-1000} '$3%2==0 && $3>uid_min && $3!=65534{print $6}' /etc/passwd
필요 없음
cat
.awk
출력을 루프의 입력으로 사용하십시오read
.while read USER_HOME_DIR ; do ... ; done < $(awk...)
. 이는awk
하나의 프로세스만 생성하면 되는 반면 원본 스크립트는awk
각 줄에 대해 별도의 프로세스를 생성하므로 더 효율적이라는 것을 이해하십시오 .awk
1000보다 큰 UID로 제한하려면 프로그램에 검사를 추가하십시오 . 그렇지 않으면 많은 시스템 사용자에 대해 실수로 복사본을 실행하게 됩니다.위의 #1에서는 사용자 이름 대신 사용자의 홈 디렉터리를 추출
$1
하도록 변경했습니다 .$6
방금 내 데비안 컴퓨터에 UID 65534를 가진 "아무도 없는" 사용자가 있다는 것을 알았으니 이를 고려해볼 수도 있습니다.
awk
이에 따라 #1의 설명을 수정했습니다 .사용자 Jeff Schaller의 의견을 바탕으로 사용자
awk
지정 최소 UID를 고려하도록 프로그램을 수정했습니다.${UID_MIN:-1000}
이 양식은 값이 원래 null이거나 설정되지 않은 경우 값을 1000으로 설정합니다.
답변4
한 문장으로 할 수 있을 것 같아요. 이것을 살펴보십시오:
eval $(awk -v source="/root/nbu/file1.sh" -v uid_min=${UID_MIN:-1000} -F: '$3%2==0 && $3>uid_min && $3!=65534{printf "cp %s %s ;", source, $6 }' /etc/passwd)
가독성을 위해:
eval $(
awk \
-v source="/root/nbu/file1.sh" \
-v uid_min=${UID_MIN:-1000} \
-F: '
$3%2==0 && $3>uid_min && $3!=65534 {
printf "cp %s %s ;", source, $6
}
' /etc/passwd
)