사용자(와일드카드) 홈 디렉터리에 파일을 복사하는 Bash 스크립트

사용자(와일드카드) 홈 디렉터리에 파일을 복사하는 Bash 스크립트

/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

당신은 매우 재주가 있어 보여서 스크립트를 제공하지는 않겠습니다. 그러나 다음은 몇 가지 팁입니다.

  1. awk당신은 그것을 잘못 사용하고 있습니다 . 이 시도:

    awk -F: -v uid_min=${UID_MIN:-1000} '$3%2==0 && $3>uid_min && $3!=65534{print $6}' /etc/passwd
    
  2. 필요 없음 cat.

  3. awk출력을 루프의 입력으로 사용하십시오 read. while read USER_HOME_DIR ; do ... ; done < $(awk...). 이는 awk하나의 프로세스만 생성하면 되는 반면 원본 스크립트는 awk각 줄에 대해 별도의 프로세스를 생성하므로 더 효율적이라는 것을 이해하십시오 .

  4. awk1000보다 큰 UID로 제한하려면 프로그램에 검사를 추가하십시오 . 그렇지 않으면 많은 시스템 사용자에 대해 실수로 복사본을 실행하게 됩니다.

  5. 위의 #1에서는 사용자 이름 대신 사용자의 홈 디렉터리를 추출 $1하도록 변경했습니다 .$6

  6. 방금 내 데비안 컴퓨터에 UID 65534를 가진 "아무도 없는" 사용자가 있다는 것을 알았으니 이를 고려해볼 수도 있습니다. awk이에 따라 #1의 설명을 수정했습니다 .

  7. 사용자 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 
  )

관련 정보