쉘 스크립트 : 내부 옵션이있는 변수 만들기


11

다음 매개 변수가있는 rsync 명령이 있습니다.

rsync -avz --{partial,stats,delete,exclude=".*"}

스크립트에서 나중에 재사용하기 위해 해당 매개 변수를 변수 안에 넣고 싶습니다. 이 같은:

#!/bin/bash
VAR=rsync -avz --{partial,stats,delete,exclude=".*"}
$VAR /dir1 /dir2

따옴표, 작은 따옴표, 괄호로 시도했지만 성공하지 못했습니다.


SO에 대한 비슷한 질문 : stackoverflow.com/questions/13365553/…
Barmar

이전에이 경로를 사용하지 않은 경우 : 최종 결과 명령 문자열에 빈 문자열이 없는지 확인하십시오. 그렇다면 rsync가 매개 변수로 매개 변수를 사용할 수 있으며 보이지 않기 때문에 디버깅하기가 어렵습니다. 빈 첫 번째 매개 변수가 있었고 rsync는 복사 할 소스의 현재 디렉토리를 포함하는 것으로 해석했습니다.
Joe

답변:


12

복잡한 명령을 변수에 넣는 것은 절대 권장되지 않는 방법입니다. BashFAQ / 050 참조 -변수에 명령을 넣으려고하는데 복잡한 경우는 항상 실패합니다!

변수 대신 함수를 사용하고 인수를 전달하기로 결정하면 요구 사항이 실제로 간단 해집니다.

같은 것

rsync_custom() {
    [ "$#" -eq 0 ] && { printf 'no arguments supplied' >&2; exit 1 ; }
    rsync -avz --{partial,stats,delete,exclude=".*"} "$@"
}

이제 필요한 인수를 다음과 같이 전달하십시오.

rsync_custom /dir1 /dir2

함수 정의는 아주 간단합니다. 먼저 $#0이 아니어야 하는 변수 를 사용하여 입력 인수 개수를 확인합니다 . 인수가 제공되지 않았다는 오류 메시지가 표시됩니다. 유효한 인수가 있으면 "$@"함수에 제공된 실제 인수 를 나타냅니다.

이것은 당신이 또한 스크립트 / 명령 줄에서 즉, 꽤 자주 사용하는 것입니다 함수 인 경우, 쉘 시작-파일에 추가 .bashrc, .bash_profile예를 들면.

또는 언급했듯이 가새 확장을 확장하여 가독성을 높이기 위해 args를 분리하는 것이 좋습니다.

rsync_custom() {
    [ "$#" -eq 0 ] && { printf 'no arguments supplied' >&2; exit 1 ; }
    rsync -avz --partial --stats --delete --exclude=".*" "$@"
}

5
VAR=rsync -avz --{partial,stats,delete,exclude=".*"}

이 시도는 명령 실행 -avz인수 --partial, --stats등 ..과와 VAR세트로 rsync된 환경에서 사용해주십시오.

VAR='rsync -avz --{partial,stats,delete,exclude=".*"}'

괄호가 따옴표로 확장되지 않고 내부 어설 션이 아니고 변수가 확장 된 후에도 확장되지 않기 때문에 따옴표 붙은 양식이 작동하지 않습니다.

명령 행 인수를 변수에 저장해야하는 경우 배열을 사용하십시오.

args=(rsync -avz --{partial,stats,delete,exclude=".*"})

지금 "${args[@]}"까지 확장됩니다 rsync, -avz, --partial별개의 단어로, 등.

배열을 사용하면 필요한 경우 조건에 따라 옵션을 목록에 추가 할 수 있습니다. 예를 들면 다음과 같습니다.

args=(this that)
if something ; then
    args+=(another_arg)
fi
"$cmd" "${args[@]}"

1

적어도 옵션을 변수에 부분적으로 저장할 수 있습니다.

opts=$(echo --{ignore-case,word-regexp,count,exclude='"sys*.*"'})

마스킹이 어려울 수 있으므로 테스트가 중요합니다.

echo $opts
--ignore-case --word-regexp --count --exclude="sys*"

grep $opts bytes *.log 

히스토리 사용, 별명 사용, 함수 사용과 같은 여러 가지 대안이 있기 때문에 내가 생각할 수있는 명확한 유스 케이스는 없습니다. 다른 프로그램 간에는 복잡한 옵션 공유가 거의 없으므로 대화식 쉘을위한 임시 솔루션의 경우 앨리어싱이 더 나은 방법으로 보입니다.

alias cgrep='grep --ignore-case --word-regexp --count --exclude="sys*"'
cgrep bytes *.log

샘플

VAR=rsync -avz --{partial,stats,delete,exclude=".*"}

과제는 첫 번째 공백에서 endet이기 때문에 작동하지 않습니다. 공백을 숨겨야합니다.

VAR='rsync -avz --{partial,stats,delete,exclude=".*"}'

--delete 옵션을 사용하여 테스트하기에 매우 위험한 것은 아닌가요? 옵션에는 ","및 작은 따옴표가 다시 포함될 수 있으므로 마스킹이 곧 어려워 질 수 있습니다. 나는 별명을 찾거나 역사에 의존합니다.

별칭은 ~ / .bashrc 파일에 저장하여 여러 세션에서 계속 사용할 수 있습니다. 함수는 bashrc에도 저장할 수 있지만 매개 변수를 처리하려는 경우 함수로 전달하여 평가할 함수 만 필요합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.