다음과 같은 기존 bash 스크립트가 있습니다.
find /path/to/my/stuff -type d -exec sh -c 'cd "$0"; /path/to/my/script.sh function_name fn_parameter' {} \;
/path/to/my/stuff
및 을 변경합니다 fn_parameter
. 나도 가끔 변화가 필요해요 function_name
.
이 명령을 계속 다시 입력하는 것은 지루하므로 다른 스크립트로 래핑하고 다음과 같이 세 가지 매개 변수만 전달하고 싶습니다.
wrapper.sh function_name "/path/to/my/stuff" fn_parameter
참고 사항: "function_name"이 가장 자주 변경되지 않는 항목이기 때문에 매개변수의 순서를 변경했습니다.
이 래퍼 스크립트를 만들려고 하면 인용과 탈출에 압도됩니다. shellcheck.net에서 스크립트를 살펴보고 배열을 사용해 보았지만 cmd
(아래에서 실패한 시도 중 하나 참조) 성공하지 못했습니다. 따옴표와 백슬래시가 존중되지 않는 것이 문제일 가능성이 높다는 것을 알고 있지만 이 문제를 해결하는 방법을 이해할 수 없습니다.
이것은 내가 실패한 수많은 시도 중 하나입니다.
래퍼.sh
#!/bin/bash
function_name=$1
mpath="$2"
arg=$3
find "$mpath" -type d -exec sh -c "cd \"$0\"; /path/to/my/script.sh $function_name $arg" {} \;
실패한 시도의 또 다른 예는 다음과 같습니다.
#!/bin/bash
function_name=$1
mpath="$2"
arg=$3
cmd="'cd \$0; /path/to/my/script.sh $function_name $arg'"
echo "find \"$mpath\" -type d -exec sh -c $cmd {} \;"
find "$mpath" -type d -exec sh -c $cmd {} \;
위의 예에서 명령줄에 echo 문의 출력을 입력하면 제대로 작동합니다. 그러나 래퍼는 다음과 같이 실패합니다.
$0;: -c: line 1: unexpected EOF while looking for matching `''
$0;: -c: line 2: syntax error: unexpected end of file
완전성을 위해 myscript.sh는 다음과 같습니다.
#!/bin/bash
fn1() {
...
}
fn2() {
...
}
fn3() {
...
}
"$@"
답변1
코드의 두 가지 변형은 각각 호출하는 인라인 스크립트에 특수 값을 전달합니다 find
.
#!/bin/sh
mpath=$1
fn_name=$2
fn_arg=$3
find "$mpath" -type d -exec sh -c '
cd "$3" && /path/to/my/script.sh "$1" "$2"' sh "$fn_name" "$fn_arg" {} \;
디렉터리를 찾으면 두 변수의 값을 디렉터리 경로 매개 변수 앞의 두 첫 번째 인수로 find
스크립트에 전달하기만 하면 됩니다 . fn_name
스크립트 내에서 처음 두 매개변수를 스크립트의 매개변수로 사용하고 세 번째 매개변수를 디렉터리 경로로 사용합니다.fn_arg
sh -c
cd
문자열 이 $0
포함됩니다 sh
. 쉘은 생성될 수 있는 모든 오류 메시지에 이 (임의의) 문자열을 사용합니다(질문에 예제를 표시했습니다). 그 $0
가치는아니요위치 매개변수 목록의 일부입니다.
또 다른 변형은 한 번에 가능한 많은 디렉터리 경로를 사용하여 인라인 스크립트를 호출하는 것입니다.
#!/bin/sh
mpath=$1
fn_name=$2
fn_arg=$3
find "$mpath" -type d -exec sh -c '
fn=$1 arg=$2; shift 2
for dirpath do
( cd "$dirpath" && /path/to/my/script.sh "$fn" "$arg" )
done' sh "$fn_name" "$fn_arg" {} +
\;
명령 끝에서 으로 변경하여 다음과 같이 호출합니다.+
find
sh -c
일괄디렉터리 경로를 찾았습니다. 그런 다음 인라인 스크립트는 이를 반복하고 각 스크립트를 차례로 호출해야 합니다.
인라인 스크립트는 먼저 위치 인수 목록에서 함수 이름과 인수를 선택하고 해당 목록에서 제거합니다. 그런 다음 나머지 매개변수와 호출 cd
및 각 매개변수에 대한 스크립트를 반복합니다. 다음은 추가 공기가 삽입된 인라인 스크립트입니다.
fn=$1 # 1st argument from find
arg=$2 # 2nd argument from find
shift 2 # remove them from the list
# Iterate over the remaining arguments
for dirpath do
( cd "$dirpath" && /path/to/my/script.sh "$fn" "$arg" )
done
cd
스크립트를 실행할 때마다 "반환"할 필요 가 없도록 하위 쉘에서 루프 본문을 실행합니다 .
이 코드를 실행하는 데 결함이 없기 sh
때문에 여기서 대신 사용하고 있습니다 . 또한 여기에 표시된 명령은 표준 기능만 사용합니다.bash
sh
find
답변2
제가 생각해낸(그리고 작업한) 해결책은 다음과 같습니다.
#!/bin/bash
function_name=$1
mpath="$2"
marg=$3
while IFS= read -r -d '' sdir
do
cd "$sdir"
/path/to/my/script.sh "$function_name" "$marg"
done < <(find "$mpath" -type d -print0)
편집: 의견에 대한 응답으로 이 솔루션은 상대 경로에서는 작동하지 않습니다.