Bash - 작은따옴표를 추가하는 명령 대체

Bash - 작은따옴표를 추가하는 명령 대체

심각한 악센트를 평가할 때 bash 동작에 문제가 있습니다. 선택적인 -name을 사용하여 find를 실행하고 싶습니다.

find -name "*.log"

잘 작동하지만 중첩된 스크립트에서 -name 부분을 가져오려는 경우

find `echo "-name \"*.log\""`

전혀 작동하지 않습니다. bash -x에서 실행하면 명령이 다음과 같이 평가되는 것을 볼 수 있습니다.

find -name '"*.log"'

분명히 작은 따옴표 때문인 것 같습니다. 이를 제거할 수 있는 해결 방법이 있습니까? 감사합니다.

//요청한 운영 체제 및 bash 버전: Debian, 7.8 wheezy, Bash 4.2.37(1)-release

답변1

Bash는 아직 명령에 작은따옴표를 추가하지 않습니다. 표시되는 작은따옴표는 명령에 유효한 bash 구문이 표시되도록 추가되었습니다. 네가 본다면

find -name '"*.log"'

이는 bash가 이 명령을 실행하라는 지시를 받는다는 것을 의미합니다: find두 개의 인수 -name"*.log"(큰따옴표는 인수의 일부입니다). 정확히 이와 같이 입력하거나 다른 유사한 방법으로 입력할 수 있습니다.

find -name \"*.log\"
find -name "\"*.log\""
find -name '"*.'log""\"

이제 당신이 쓴 내용을 살펴 보겠습니다.

find `echo "-name \"*.log\""`

서브쉘에서 실행하는 명령은 다음과 같습니다.

echo "-name \"*.log\""

그 출력은

-name "*.log"

여기서 매개변수의 큰따옴표가 유래됩니다. 명령 대체의 출력이 명령줄에 삽입되면 쉘 구문으로 구문 분석되지 않습니다.

find `echo '; rm -rf ~'`

모든 파일을 삭제하지는 않지만 ;첫 번째 인수 find, rm두 번째 인수, -rf세 번째 인수로 전달하고 홈 디렉터리(특수 문자가 포함되어 있지 않다고 가정)를 네 번째 인수로 전달합니다.

변수 대체 또는 명령 대체가 큰따옴표 밖에 있으면 변수 값이나 명령 출력이 다음과 같이 변환됩니다.

  1. 명령 대체에만 해당: 후행 줄 바꿈을 제거합니다.
  2. 문자열은 공백으로 구분된 세그먼트로 나뉩니다. (변수를 설정하여 구분 기호를 구성할 수 있습니다 IFS.) 이 변환 결과는 다음과 같습니다.목록끈.
  3. 목록의 각 요소는 와일드카드 패턴으로 해석됩니다. 패턴이 파일과 일치하면 해당 요소는 일치하는 파일 목록으로 대체됩니다.와일드카드). 패턴이 파일과 일치하지 않으면 요소가 유지됩니다.

2단계 -name "*.log"문자열을 -name과 의 두 부분으로 나눕니다 "*.log". 어느 부분도 파일과 일치하지 않으므로 결과는 두 단어 -name의 합 입니다 "*.log".

당신이 원하는 것은 find매개 변수를 사용 -name하고 실행하는 것입니다 *.log. 와일드카드를 꺼서 이 작업을 수행할 수 있습니다.

set -f
find `echo -name *.log`
set +f

이는 강력하지 않습니다. 예를 들어 공백이 포함된 파일 이름을 전달할 수 없습니다. 일반적으로 명령의 일부 비트를 변수에 저장하거나 명령에 전달하여 명령을 작성해서는 안 됩니다. 현재 하고 있는 일을 수행하는 가장 좋은 방법은 실제로 하고 싶은 일이 무엇인지에 달려 있습니다. 다음은 몇 가지 일반적인 제안 사항입니다.

답변2

eval 함수를 사용하면 문제가 해결됩니다.

command="find `echo \"-name \"*.log\"\"`"   response=$(eval "$command")

관련 정보