경로 아래의 각 디렉터리에 대해 해당 디렉터리에서 쉘 스크립트를 실행합니다(find -execdir이 적절하지 않은 경우).

경로 아래의 각 디렉터리에 대해 해당 디렉터리에서 쉘 스크립트를 실행합니다(find -execdir이 적절하지 않은 경우).

다음과 같은 기존 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_argsh -ccd

문자열 이 $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" {} +

\;명령 끝에서 으로 변경하여 다음과 같이 호출합니다.+findsh -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때문에 여기서 대신 사용하고 있습니다 . 또한 여기에 표시된 명령은 표준 기능만 사용합니다.bashshfind

답변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)

편집: 의견에 대한 응답으로 이 솔루션은 상대 경로에서는 작동하지 않습니다.

관련 정보