내가 만든 bash 스크립트에 문제가 있습니다. for 루프 내에서 모든 매개변수를 반복하여 나중에 "eval" 명령에 입력될 문자열 변수를 구성합니다.
for arg in "$*"
do
if [ $arg != $lastArg ]; then
findTarget+="-name $arg -o "
else
findTarget=$(echo $findTarget | sed 's/-o$//')
break
fi
done
문제는 "$*"에서 발생합니다. 예를 들어, 매개변수에 "*.c"를 입력하고 현재 폴더에 해당 패턴과 일치하는 파일이 포함되어 있으면 매개변수가 *.c
해당 파일로 확장됩니다. 저는 이를 원하지 않습니다. findTarget
와 연결 하려고 -name *.c -o
합니다. eval을 사용하고 따옴표 없이는 효과가 없는 것 같습니다. 이 작업을 수행하는 방법을 아시나요(가능하다면 간단하게)? 참고: 총 매개변수 수는 다를 수 있습니다.
다음은 스크립트를 실행하는 방법의 예입니다.
$ trouver.bash *.c *.f90 someString
내 for 루프가 끝나면 변수는 findTarget
다음과 같아야 합니다.-name *.c -o -name *.f90
*.c
*.f90
현재 폴더의 파일과 일치 하거나 일치하는 경우에는 아무런 효과가 없습니다.
답변1
위치 매개변수를 반복하는 구문은 for arg do
별개입니다. "$*"
는 첫 번째 문자와 위치 인수를 연결한 것이므로 $IFS
하나의 요소만 반복하게 됩니다.
또한 명령에 대한 매개변수 목록을 작성하려면 find
문자열이 아닌 배열이 필요합니다. 그리고 변수를 인용하는 것을 잊지 마세요!
그래서:
findTarget=()
or=()
for arg
do
[ "$arg" = "$lastArg" ] && break
findTarget+=("${or[@]}" -name "$arg")
or=(-o)
done
find . \( "${findTarget[@]}" \)
스크립트를 호출할 때 필요한 사항에 유의하세요.인용하다...mode *.c
그렇지 않으면 스크립트에 전달되기 전에 셸에 의해 확장됩니다.
trouver.bash '*.c' '*.f90' someString
대화형 셸이 인 경우 zsh
와일드카드를 비활성화하여 명령에 대한 별칭을 정의할 수 있습니다.
alias trouver.bash='noglob trouver.bash'
이 방법으로 다음을 수행할 수 있습니다.
trouver.bash *.c *.f90 someString
이 구체를 확장하는 껍질은 없습니다 *.c
*.f90
.
답변2
"$*"
모든 매개변수를 하나의 긴 매개변수로 연결하려면 메서드를 사용하세요 . 이를 다음으로 변경하면 "$@"
인수 목록이 제공됩니다. 하지만 실제로 for arg in "$@"
올바른 관용구를 사용할 필요는 없습니다 for arg
.
-o
그런 다음 각 새 매개변수에 대해 하나를 추가하여 사용할 수 있습니다 ${findTarget[@]+"-o "}
.
값이 할당되지 않으면 null이 되고, 값이 할당되면 findTarget
일반 문자열이 됩니다. 첫 번째 루프 실행에서는 null로 축소되고 다음 루프에서는 null이 됩니다.-o
findTarget
-o
(( $# < 1 )) && echo "please provide some argument(s)" && exit 1
unset findTarget
for arg
do [[ "$arg" == "$lastArg" ]] && break
findTarget+=("${findTarget[@]+"-o "}-name $arg")
done
find . \( "${findTarget[@]}" \)
다음과 같이 스크립트를 실행해야 합니다.
$ trouver.bash '*.c' '*.f90' someString
원하는 대로 각 인수는 쉘에 의해 확장되지 않습니다(작은따옴표를 사용하십시오. 큰따옴표는 작동할 수 있지만 확장 없이 인수를 유지하려는 의도를 명확하게 표현하지는 않습니다).
"작은따옴표" 없이 스크립트를 사용해야 하는 경우 "경로 이름 확장"(set -f)을 제거하여 확장을 방지할 수 있습니다 *
.
$ ( set -f; trouver.bash *.c *.f90 someString )
이렇게 하면 ()
noglob에 대한 변경 사항이 현재 실행 중인 쉘에 영향을 미치는 것을 방지할 수 있습니다.
이는 스크립트가 결과를 작성 stdout
하고 하위 쉘 내에서 인쇄할 수도 있기 때문에 작동합니다 (…)
.