접두사

접두사

쉘 스크립트를 통해 이 콘텐츠가 포함된 파일을 생성 해야 합니다 /opt/nginx/conf.d/default.conf. 파일이 없으면 생성해야 합니다.

server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name _;
    root /usr/share/nginx/html;
}

쉘 스크립트를 통해 여러 줄의 내용을 작성하는 방법은 무엇입니까?

디렉터리를 만들었습니다.

sudo mkdir -p /opt/nginx/conf.d

하지만 파일에 쓰는 방법을 모르겠습니다.

답변1

요약: >>추가용, [ -f file ]테스트용입니다.

노력하다

if [ ! -f myfile ]
then
   cat <<EOF > myfile
server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name $server ;
    root /usr/share/nginx/html;
}
EOF
fi
  • 이 구문 cat <<EOF을 "여기 문서".
  • $server해당 값으로 대체되거나 정의되지 않은 경우 비어 있습니다.
  • 지적했듯이 작은따옴표를 사용하면 'EOF'var가 있는 경우 var를 바꾸는 것을 방지할 수 있습니다.
  • 에코가 여러 개 있을 수도 있습니다(너무 많으면 유지 관리가 어려울 수 있음).

    echo "## foo.conf" > foo.conf
    echo param1=hello >> foo.conf
    echo param2=world >> foo.conf
    

접두사

Bash에는 직접 추가가 없습니다. 임시 파일을 사용하거나

mv file file_tmp
cat new_content file_tmp > file
rm file_tmp

아니면 수정하세요

sed -i -e '1r new_file' -e 'wq' file

답변2

/opt/nginx/conf.d/default.conf 파일이아니요존재하는 경우 정적 문자열을 파일에 인쇄(f)합니다.

[ -f /opt/nginx/conf.d/default.conf ] || printf 'server {\n    listen 80 default_server;\n    listen [::]:80 default_server;\n    server_name _;\n    root /usr/share/nginx/html;\n}\n' > /opt/nginx/conf.d/default.conf

답변3

개행 문자를 에 전달하는 것을 막을 수 있는 것은 없습니다 echo. 작은 따옴표나 큰 따옴표 안의 개행 문자는 Bourne과 같은 쉘의 다른 문자보다 더 특별하지 않습니다.

if [ ! -e "$file" ]; then
  echo "server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name $server;
    root /usr/share/nginx/html;
}" > "$file"
fi

마지막 줄 구분 기호 자체를 추가하지 않는다는 점에 유의하세요 echo.

출력하려는 ​​텍스트에 백슬래시가 포함되어 있거나 로 시작하는 경우 -이를 대신 사용할 수 있습니다 printf. for 또는처럼 후행 줄 바꿈을 자동으로 추가한 printf '%s\n' "text"다음 출력하려는 ​​텍스트에 줄 바꿈을 추가합니다.echoprintf %s

if [ ! -e "$file" ]; then
  printf %s "server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name $server;
    root /usr/share/nginx/html;
}
" > "$file"
fi

인쇄될 각 인수에 여러 인수를 전달하고 개행을 추가할 수도 있으므로 다음과 같이 할 수 있습니다 printf '%s\n' ....printf

new_lines=(
  'server {'
  '  listen 80 default_server;'
  '  listen [::]:80 default_server;'
  "  server_name $server;"
  '  root /usr/share/nginx/html;'
  '}'
)
[ -e "$file" ] || printf '%s\n' "${new_lines[@]}" > "$file"

여기에서 각 행에 사용할 참조 유형을 결정합니다.

그러나 매개변수가 전달되지 않으면 printf '%s\n'여전히 빈 줄이 인쇄됩니다. 에서는 대신 사용할 zsh수 있습니다 print -rC1 --. 또는 다음 중 하나를 정의할 수 있습니다.

println() {
  [ "$#" -eq 0 ] || printf '%s\n' "$@"
}

접근성.

또한 대상이 일반 파일로 존재하는 경우 noclobberPOSIX 셸의 옵션으로 인해 >리디렉션 연산자가 실패하게 됩니다.

그래서:

set -o noblobber # same as set -C
printf '%s\n' "$newcontent" > "$file"

이미 존재하는 경우(일반 파일로) $newcontent에 기록되지 않는 것이 보장됩니다 $file. 장치(예: 심볼릭 링크 /dev/null), 디렉토리 또는 fifo 등인 경우 $newcontent에는 여전히 기록되지 않습니다. TOCTOU 경쟁 조건을 완전히 피하십시오. 왜냐하면 쉘은 여전히 ​​파일 유형을 먼저 확인해야 하기 때문입니다.

유형에 관계없이 이미 존재하는 파일을 경쟁 없이 작성하지 않으려면 다음 플래그를 사용하여 파일을 zsh열 수 있는 이 기능을 사용할 수 있습니다.O_EXCL

zmodload zsh/system
(sysopen -w -o excl -u 1 -- $file && print -r -- $newcontent > $file)

큰따옴표 안에 백슬래시가 앞에 오지 않는 한 1입니다.

관련 정보