
자주 사용하는 명령을 대체하기 위해 bash 스크립트를 작성하려고 합니다. 내 파일에 있는 코드입니다.test.sh
#!/bin/bash
echo -e "\n"
i=0
args[i++]=$0
for arg in $@ ; do
args[i++]=$arg
done
where="."
what="-type f"
gcase=
str=
while getopts "d:f:F:ih" opt ; do
case $opt in
h)
echo -e "This is the help of this search function."
echo -e "\t $0 [-d <dir>] [-f|-F <pattern>] [-i] string"
echo -e "This will output the result of"
echo -e "\t find dir -[i]name pattern -exec grep --color -Hn[i] string {} \;"
echo -e "Default is"
echo -e "\t find . -type f -exec grep --color -Hn string {} \;\n"
exit 0
;;
d)
OPTIND=$(($OPTIND-1))
where=
tmp=${args[$OPTIND]}
while [[ $OPTIND -lt $# ]] && [[ "${tmp:0:1}" != "-" ]] ; do
where="$where"" $tmp"
OPTIND=$(($OPTIND+1))
tmp=${args[$OPTIND]}
done
;;
F)
what="-iname "
what="$what""\"$OPTARG\""
;;
f)
what="-name "
what="$what""\"$OPTARG\""
;;
i)
gcase="-i"
;;
\?)
echo "Invalide option, use option -h for help." >&2
exit 0
;;
esac
done
str=${args[$OPTIND]}
command="find $where $what -exec grep --color -Hn $gcase \"$str\" {} \;"
echo "$command"
$command
이제 터미널에서 이렇게 하면 다음 ./test.sh -d auto-avoid -F "TEST*" "main"
과 같은 결과가 나옵니다.
find auto-avoid -iname "TEST*" -exec grep --color -Hn "main" {} \;
find: missing argument to `-exec'
( auto-avoid
내가 재미로 작성한 작은 C++ 프로그램이 포함된 디렉토리입니다.)
그런 다음 터미널에 명령을 복사하여 붙여 넣으면 다음과 같은 결과가 find auto-avoid -iname "TEST*" -exec grep --color -Hn "main" {} \;
나타납니다.
auto-avoid/test.cpp:26:int main(int argc, char **argv)
이는 예상된 결과입니다.
문제는 내가 무엇을 놓치고 있는가?
지금은 테스트하기 위해 독립형 스크립트로 작성하고 있지만 목표는 이를 내 .bash_aliases
.
비슷한 주제를 찾았지만 아무것도 도움이 되지 않았습니다. 이 질문이 중복된 질문이라고 생각되면 기꺼이 답변해 드리겠습니다.
어떤 사람들은 나에게 를 사용하라고 말할 것이라고 확신합니다grep -r
. 하지만 적어도 내 스크립트가 작동하지 않는 이유를 이해하고 싶습니다. 이것은 최소한의 "작동하지 않는" 예입니다. 나중에 일부 디렉토리를 제외하겠습니다 find
.
답변1
사용set -x
쉘이 실제로 실행하려고 하는 것이 무엇인지 확인하십시오.
$ command='find foo -iname "TEST*" -exec grep --color -F -Hn "main" {} \;'
$ echo "$command"
find foo -iname TEST* -exec grep --color -F -Hn main {} \;
$ set -x
$ $command
+ find foo -iname 'TEST*' -exec grep --color -F -Hn main '{}' '\;'
find: missing argument to `-exec'
참고 '\;'
: 문자 그대로 백슬래시를 제공하고 있는데 find
이는 예상한 것과 다릅니다.
큰따옴표는 백슬래시와 동일한 기능을 수행하며 세미콜론을 이스케이프하여 명령 구분 기호가 아닌 문자로 처리됩니다.
다음은 동일해야 합니다.
$ foo="something ;"
$ foo=something\ \;
또한 명령줄을 실행하는 것은 $command
약간 번거롭다는 점에 유의하세요. 생성된 명령에 대한 인수(예: pathname )에 공백이 있으면 $where
분할됩니다.쉘 배열이를 수행하는 보다 강력한 방법을 제공합니다.