Bash 스크립트에서는 매개변수와 함께 명령을 전달합니다. 명령에 리디렉션이 포함되어 있지 않으면 제대로 작동합니다. 이 경우 리디렉션 문자는 일반 문자로 처리됩니다.
$ cat foo
#!/bin/bash
f() {
echo "command: $@"
$@
}
f echo a-one a-two
f 'echo b-one b-two'
f 'echo c-one c-two > c.tmp'
# I don't want to do f echo d-one d-two > d.tmp because I want to redirect the
# output of the passed command, not the output of the f() function.
$ ./foo
command: echo a-one a-two
a-one a-two
command: echo b-one b-two
b-one b-two
command: echo c-one c-two > c.tmp
c-one c-two > c.tmp
보시다시피 "c-one c-two"를 c.tmp 파일에 인쇄하려고 하면 "c-one c-two > c.tmp"가 인쇄됩니다. 이를 수행할 수 있는 방법이 있습니까?
답변1
f() {
echo "command: $@"
$@
}
일반적으로 말하자면, 당신은사용해야한다"$@"
, 여기도 있어요대개 이유.
그러나 당신 말이 맞습니다. 이와 같은 명령을 실행하면 쉘 연산자가 처리되지 않으며 리디렉션 이나 &&
.eval
특히 임의의 파일 이름을 전달하는 것이 다시 어려워집니다. 예를 들어, 이는 궁극적으로 다음 ls
두 파일에서 실행 됩니다 foo
.bar
run_with_eval() {
eval "$@"
}
file='foo bar'
run_with_eval ls -l "$file"
당신은해야합니다참조할 파일 이름 정렬이는 쉘에 약간 어색하고 오류가 발생하기 쉽습니다.
하지만 만약 당신이오직리디렉션하거나 더 나은 방법으로 출력 전용 리디렉션을 수행하려면 >
함수가 이를 수동으로 처리하도록 할 수 있습니다.
#!/bin/bash
run_with_redir() {
local redir=
if [[ $1 = '>' ]]; then
redir=$2
shift 2
fi
## whatever else you do
if [[ $redir ]]; then
"$@" > "$redir"
else
"$@"
fi
}
run_with_redir echo "normal command, no redirection"
run_with_redir ">" output.txt echo "this gets redirected to output.txt"
즉, >
파일 이름을 처음 두 개의 인수로 사용하여 함수를 호출하고, 나머지 인수를 명령으로 실행하고, 출력을 리디렉션합니다. 그렇지 않은 경우 >
정상적으로 명령을 실행합니다. ">"
함수를 호출할 때 따옴표를 넣어야 합니다. 그렇지 않으면 전체 함수의 출력 리디렉션이 다시 발생합니다 . 예를 들어 이를 지원하기 위해 확장하는 것은 >>
중복이더라도 사소한 일입니다.
이는 더 까다로운 경우에도 작동합니다.
run_with_redir ">" "output file with space.txt" ls -l "other file with space"
답변2
eval "$@"
작업을 수행합니다:
#!/bin/bash
f() {
echo "command: $@"
eval "$@"
}
하지만 일반적으로 보더라도 사용하기에는 매우 안전하지 않습니다. 여기 저기에.
답변3
eval을 사용하지 않는 방법이지만 매우 안전하지도 않습니다.
#!/bin/bash
f() {
echo "command: $@"
bash -c "$@"
}
f echo a-one a-two
f 'echo b-one b-two'
f 'echo c-one c-two > c.tmp'