변수에 unix 명령이 있는데 다음과 같습니다.
cmd="find /path/to/webpage -type f | grep -v .svn | xargs grep $@"
`$cmd`
find: paths must precede expression
Usage: find [-H] [-L] [-P] [path...] [expression]
$cmd
Bash 스크립트에서 명령을 실행 하려고 하면 작동하지 않습니다. 그러나 똑같은 명령을 복사하여 붙여넣으면 작동합니다. 내가 뭘 잘못하고 있는지 알려주실 수 있나요?
경로 주위에 따옴표를 넣으려고 시도했지만 동일한 오류가 발생했습니다.
cmd="find \"/path/to/webpage\" -type f | grep -v .svn | xargs grep $@"
find: paths must precede expression
Usage: find [-H] [-L] [-P] [path...] [expression]
매개변수를 제거하면 -type f
다음 오류가 발생합니다.
cmd="find /path/to/webpage | grep -v .svn | xargs grep $@"
find: invalid predicate `-v'
이로 인해 파이프가 인식되지 않는 것 같습니다. 작동하게 하려면 어떻게 해야 하나요?
답변1
다른 사람들은 그것을 수행하는 방법을 설명했습니다. 여기서 무슨 일이 일어나고 있는지 설명하겠습니다. |
변수가 확장되면 파이프 문자는 파이프를 형성하지 않고 리터럴 문자로 작동합니다. 따라서 find
다음 매개변수를 사용하여 실행하십시오.
{"/path/to/webpage", "-type", "f", "|", "grep", "-v", ".svn", "|", ...}
를 경로로 해석 |
하고 표현식( -type f
) 앞에 나타나야 한다고 불평합니다.
`$cmd`
또 다른 큰 실수는 그것을 유일한 명령줄 로 사용한다는 것입니다 . $cmd
(즉 find ...
) 성공하고 유사한 출력을 생성 하면 rm -rf /
사용자를 대신하여 실행됩니다.데이터를 코드로 취급할 때는 주의하세요!
개선 1. find ... | grep -v ...
출력에서 무언가를 제외하는 나쁜 방법입니다. find
이름이 지정된 전체 하위 디렉토리를 탐색하고 .svn
행이 생성되지만 나중에 삭제됩니다. 그냥 나 find
한테 하라고 하면 안 될까 ?
find path -type f | grep -v .svn # don't do this
find path -name .svn -prune -o -type f -print # do this instead
개선 2.find
and 를 결합할 때는 xargs
항상 -print0
in find
및 -0
in 을 사용하세요 xargs
.
find path ... -print0 | xargs -0 -r grep ... # I'd also recommend -r
아니면 정확히 이렇게 할 수도 있습니다 grep
:
grep --recursive --exclude-dir=.svn pattern path
답변2
실제로 변수에서 코드를 실행하려면 를 사용할 수 있습니다 eval
.
cmd="find /path/to/webpage -type f | grep -v .svn | xargs grep something"
eval "$cmd"
하지만 with 에 인수를 전달하려고 하므로 $@
필요한 것은 함수입니다.
webgrep() {
find /path/to/webpage -type f | grep -v .svn | xargs grep "$@"
}
공백 문자가 포함된 모든 경로에 문제가 발생한다는 점에 유의하세요. 또는 빼기 기호로 시작하는 패턴입니다. .svn
디렉터리를 무시하기 전에 디렉터리의 전체 내용을 검사해야 합니다. 사용자가 실수로 여러 매개변수를 전달하는 경우(예: 스키마가 올바르게 인용되지 않은 경우)를 처리하는 것이 좋을 것입니다. 더 좋은 방법은
webgrep() {
find /path/to/webpage -name .svn -prune -o -type f -exec grep -e "$*" {} +
}
그런 다음 이렇게 부르세요
webgrep PATTERN
답변3
다음과 같이 변수를 만들어 보세요.
cmd=$(find /path/to/webpage -type f | grep -v .svn | xargs grep $@)
또는
cmd=`find /path/to/webpage -type f | grep -v .svn | xargs grep $@`
또는 별칭이 더 적합할 수도 있습니다.
alias cmd="find /path/to/webpage -type f | grep -v .svn | xargs grep $@"
답변4
아니요경험상 코드를 변수에 넣으세요. 기능을 사용하세요.
cmd() {
find /path/to/webpage -type f |
grep -v .svn |
xargs grep $@
}
cmd "$@"
결국 넣어야 한다면단순한코드는 변수에 있습니다(그렇지 않지만 그렇게 한다면...). 위에서 언급한 대로 파이프 같은 것을 삽입하거나 eval
... 없이 리디렉션할 수 없습니다. 그것도 하지 마세요, 하하
그러나 하위 쉘에서 명령을 실행하고 이를 출력으로 바꾸는 백틱 내에서 실행하지 마십시오. 그러면 출력은 파서가 실행 명령으로 수신하는 것이 됩니다.
$: `echo foo`
bash: foo: command not found