내 Bash 스크립트에서는 find를 사용하여 와일드카드로 폴더 이름을 가져옵니다.
for i in $(find ${directory} -mindepth 1 -type d -name ${wildcard});
do
stuff=doStuff ${i}
done
doStuff() {
echo ${1}
return ${1}'/hello';
}
문제는 이 작업을 수행할 때 다음 오류가 발생한다는 것입니다(${i}가 "home/me/my_directory"에 해당한다고 가정).
line 111: '/home/me/my_directory': is a directory.
(라인 111은 "doStuff"가 있는 라인입니다)
나는 이것을 시도했지만 소용이 없었습니다.
for i in $(find ${directory} -mindepth 1 -type d -name ${wildcard});
do
stuff=doStuff "${i}"
done
분명히 이것은 프로그램이 디렉토리를 실행하려고 하기 때문이지만 나는 그것을 조작할 수 있는 문자열로 원합니다.
답변1
따옴표와 명령 대체가 문제입니다.
당신이 겪고 있는 구체적인 문제는 쉘이 /home/me/my_directory
환경 변수를 사용하여 호출된 명령을 실행하려고 하기 때문입니다 stuff=doStuff
.
당신이 정말로 원하는 것은 (제가 올바르게 해석한다면) doStuff
의 값을 $i
인수로 사용하여 실행하고 출력을 변수에 할당하는 것 입니다 stuff
. 이를 수행하는 방법은 명령을 $()
.
stuff="$(doStuff "$i")"
내가 모든 것에 따옴표를 어떻게 넣었는지 주목하세요. 이는 쉘이 토큰화하기를 원하지 않는 것을 토큰화하는 것을 방지하기 위한 것입니다( /foo/bar baz
단일 인수를 /foo/bar
and 로 바꿉니다 baz
).
또한 함수의 출력은 return
.
더 많은 따옴표를 사용해야 하므로 다른 모든 항목에도 추가해야 합니다. 다음은 스크립트의 전체 버전입니다.
doStuff() {
echo "${1}" >&2
printf '%s/hello' "$1";
}
IFS=$'\n'
for i in $(find "${directory}" -mindepth 1 -type d -name "${wildcard}");
do
stuff="$(doStuff "${i}")"
done
함수 정의를 사용하기 전에 먼저 넣어야 합니다. 쉘은 파일을 여러 번 통과하는 컴파일된 프로그램처럼 구문 분석하지 않습니다. 이것은 하향식입니다. 또한 STDERR로 보내도록
수정했으며 터미널에 표시한 다음 STDOUT으로 보내고 변수에 캡처합니다 .doStuff
echo
printf
stuff
디렉토리에 개행 문자가 포함되어 있으면 여전히 문제가 발생할 수 있습니다. 그러나 이는 쉘의 한계입니다. 파일 경로에 포함될 수 없는 유일한 문자는 NULL 문자( \0
)입니다. 그러나 bash 및 기타 쉘은 문자열에 NULL 문자를 저장할 수 없으므로(모두는 아니지만 다수. zsh는 가능하다는 것을 알고 있음) 구분 기호로 사용할 수 없습니다.
답변2
좋은 노력이지만 bash
실제로는 간단한 스크립팅 언어인데도 프로그래밍 언어처럼 작성하려고 한다는 것을 보여줍니다. 당신의 구조의 문제 는 그것이 당신이 생각하는 것을 의미하지 않는다는 stuff=doStuff arg
것입니다 . bash
To 는 bash
변수 stuff=doStuff
할당이자 arg
명령입니다. 다음 두 링크를 읽어 보시기 바랍니다.
- 명령의 반환 값 및/또는 출력을 변수에 어떻게 저장할 수 있나요?
- 함수에서 문자열(또는 큰 숫자 또는 음수)을 반환하는 방법은 무엇입니까? "return"을 사용하면 0에서 255 사이의 숫자만 제공할 수 있습니다.
당신이 가지고있는 것과 유사한 작동 버전은 다음과 같습니다
doStuff () {
echo "$1/hello"
}
stuff=$(doStuff "$i")
답변3
오류가 발생한 줄은 생각한 대로 작동하지 않습니다.
먼저 환경 변수 stuff를 "doStuff" 문자열로 설정한 다음 ${i}를 명령으로 실행하려고 시도합니다. ${i}는 디렉토리이기 때문에 주어진 오류 메시지와 함께 실패합니다.