심각한 악센트를 평가할 때 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
세 번째 인수로 전달하고 홈 디렉터리(특수 문자가 포함되어 있지 않다고 가정)를 네 번째 인수로 전달합니다.
변수 대체 또는 명령 대체가 큰따옴표 밖에 있으면 변수 값이나 명령 출력이 다음과 같이 변환됩니다.
- 명령 대체에만 해당: 후행 줄 바꿈을 제거합니다.
- 문자열은 공백으로 구분된 세그먼트로 나뉩니다. (변수를 설정하여 구분 기호를 구성할 수 있습니다
IFS
.) 이 변환 결과는 다음과 같습니다.목록끈. - 목록의 각 요소는 와일드카드 패턴으로 해석됩니다. 패턴이 파일과 일치하면 해당 요소는 일치하는 파일 목록으로 대체됩니다.와일드카드). 패턴이 파일과 일치하지 않으면 요소가 유지됩니다.
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")