큰따옴표로 묶인 변수 확장 후에 쉘 glob(와일드카드(*)) 사용

큰따옴표로 묶인 변수 확장 후에 쉘 glob(와일드카드(*)) 사용

나는 Bash의 모든 변수 확장을 큰따옴표로 묶는 것이 가장 좋은 방법이라는 것을 읽었습니다. 또한 *큰따옴표로 묶인 변수 확장 직후에는 쉘 글롭(와일드카드( ))을 사용할 수 없다는 내용도 읽었습니다 . 이러한 상황은 변수에서 확장된 정규식 패턴의 값을 사용하려고 할 때 충돌합니다.

가끔 정규식과 와일드카드를 결합하려는 이유는 정규식을 최소화하고 개인 취향에 맞게 깔끔하게 유지하기 위해서입니다.

나의 특별한 질문

mvphpmyadmin을 내 문서 루트에 다운로드하고 압축을 풀었지만 변수에 넣은 정규식 패턴을 통해 이름을 바꿀 수 없으며 변수를 확장할 때 작동하도록 할 수 없습니다. 정확한 추적은 다음과 같습니다.

userName@compName:/var/www/html# ll
total 11336
drwxr-xr-x  3 root root     4096 Feb 14 07:04 ./
drwxr-xr-x  3 root root     4096 Feb 14 06:56 ../
-rw-r--r--  1 root root      612 Feb 14 06:57 index.nginx-debian.html
drwxr-xr-x 12 root root     4096 Dec 23 08:50 phpMyAdmin-4.7.7-all-languages/
-rw-r--r--  1 root root 11589684 Dec 23 14:08 phpMyAdmin-latest-all-languages.zip
userName@compName:/var/www/html# echo $pma
[pP][hH][pP][mM][yY][aA][dD][mM][iI][nN]
userName@compName:/var/www/html# mv "$pma"*/ phpmyadmin/
mv: cannot stat '[pP][hH][pP][mM][yY][aA][dD][mM][iI][nN]*/': No such file or directory

에 표시된 대로 변수 확장을 역참조하면 ${pma}실제로 변수 확장과 정규식을 결합할 수 있었지만 ${pma}*가능하다면 예외 없이 모범 사례를 따르는 것이 중요합니다.

내 질문

변수 큰따옴표를 확장된 상태로 유지하면서 와일드카드와 함께 추출된 값을 계속 사용하는 방법은 무엇입니까?

답변1

큰따옴표를 사용하는 경우 변수에 저장된 파일 이름 globbing 패턴은 파일 이름을 와일드카드로 지정하지 않습니다. 파일 이름이 와일드카드로 처리되는 것을 방지하는 것은 큰따옴표이지 *후행 와일드카드나 따옴표와 *.

우리는 종종 웹 사이트의 사용자에게 "변수를 인용"하라고 지시하는데, 참조되지 않은 변수의 값이 토큰화 및 파일 이름 글로빙을 거치게 되기 때문에 이렇게 합니다. 이는 일반적으로 우리가 원하는 것이 아닙니다. 예를 들어, 암호는 and 일 수 [hello] world*있으며 명령줄의 암호는 -p $password현재 디렉터리에 있는 파일을 기반으로 "흥미로운" 작업을 수행합니다(공간상의 이유로 전혀 작동하지 않을 수 있습니다). 질문 "도 참조하세요.bash/POSIX 쉘에서 변수를 인용하는 것을 잊어버리는 보안 위험"

여기서 하고 싶은 일은 우리가 평소 하고 싶은 일과 정반대다.피하다즉, 변수의 파일 이름 globbing 패턴을 사용하여 파일 이름 globbing을 호출합니다.

추출된 디렉토리의 이름이 안정적이라고 믿을 수 없다면 더 나은 해결책("클리너"에서와 같이)은 이름이 안정적인지 확인하는 것입니다.오직임시 디렉토리에 항목을 넣은 다음 제자리 *로 옮기세요(아마도 이름을 알 수 있도록 프로세스에서 이름을 변경할 수도 있습니다).

이는 파일 이름 글로빙 패턴으로 인해 단순히 변수 주위의 따옴표를 제거하는 것보다 낫습니다.가능한디렉토리에서 사용 가능한 다른 항목에 따라 예상한 단일 이름 이외의 이름과 일치합니다.

내 대답의 변형은 다음과 같습니다.이전 질문:

#!/bin/sh -ex

destdir="/var/www/html/phpmyadmin"

tmpdir=$(mktemp -d)
trap 'rm -rf "$tmpdir"' EXIT    # remove temporary directory on termination

wget -O "$tmpdir/archive.zip" \
    "https://www.phpmyadmin.net/downloads/phpMyAdmin-latest-all-languages.zip"

cd "$tmpdir" && {
    unzip archive.zip
    rm -f archive.zip

    # The only thing in the current (temporary) directory now is the
    # directory with the unpacked zip file.

    mkdir -p "$destdir"
    mv ./* "$destdir"/phpmyAdmin
} 

위의 내용은 다섯 단계로 요약될 수 있습니다.

  1. 빈 디렉토리를 생성하고 현재 작업 디렉토리를 해당 디렉토리로 변경합니다.
  2. 아카이브를 받으세요.
  3. 아카이브를 추출합니다.
  4. 아카이브를 삭제합니다.
  5. 이제 빈 디렉터리에 있는 별도의 폴더 이름을 변경합니다.

답변2

변수 큰따옴표를 확장된 상태로 유지하면서 와일드카드와 함께 추출된 값을 계속 사용하는 방법은 무엇입니까?

당신은 할 수 없습니다 1 ,그리고 당신은 원하지 않습니다; 귀하의 명령은 그것들 없이도 완벽하게 작동합니다. (이 질문의 이전에 삭제된 변형 중 하나에서도 이것이 지적되었다고 확신합니다.)

$ mkdir phpMyAdmin-4.7.7-all-languages
$ pma=[pP][hH][pP][mM][yY][aA][dD][mM][iI][nN]
$ echo $pma
[pP][hH][pP][mM][yY][aA][dD][mM][iI][nN]
$ echo $pma*/
phpMyAdmin-4.7.7-all-languages/
$ mv $pma*/ phpmyadmin
$ ls
phpmyadmin

변수를 참조하는 목적은 다음을 보장하는 것입니다.쉘 와일드카드그리고필드 분할일어나지 마세요. 이번에는 실제로 그런 일이 일어나기를 원하므로 인용문은 역효과를 낳을 것입니다.

이러한 지침이 존재하는 이유는 포괄적인 규칙이 아니며, 귀하에게 적합하지 않은 경우 적용되지 않는 상황에 직면할 수 있다는 점을 이해하는 것이 좋습니다. 이해하지 못한 채 "예외 없이 모범 사례를 따르려고" 노력하는 것은 단순히 잘못된 것입니다.


그 외에도 이렇습니다.

또한 큰따옴표로 묶인 변수 확장 직후에는 쉘 glob(와일드카드(*))를 사용할 수 없다는 것도 배웠습니다.

진짜가 아니야.

$ tmp=php
$ echo "$tmp"*
phpmyadmin

1you할 수 있다를 사용 eval하지만 그것은 전혀 의미가 없으며 더 이상 후속 조치를 취하지 않겠습니다.

관련 정보