find -exec는 bash 스크립트에서는 작동하지 않지만 터미널에서는 작동합니다.

find -exec는 bash 스크립트에서는 작동하지 않지만 터미널에서는 작동합니다.

자주 사용하는 명령을 대체하기 위해 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분할됩니다.쉘 배열이를 수행하는 보다 강력한 방법을 제공합니다.

관련 정보