Linux 사용자를위한 2020 업데이트 :
Linux를 사용하는 경우와 같이 최신 버전의 bash (4.4-alpha 이상)가있는 경우 Benjamin W.의 답변 을 사용해야합니다 .
마지막으로 확인한 Mac OS에서 bash 3.2를 사용하거나 이전 bash를 사용하는 경우 다음 섹션으로 계속 진행하십시오.
bash 4.3 이하에 대한 답변
다음은의 출력을 배열 find
로 가져 오는 한 가지 솔루션입니다 bash
.
array=()
while IFS= read -r -d $'\0'; do
array+=("$REPLY")
done < <(find . -name "${input}" -print0)
일반적으로 파일 이름에는 공백, 줄 바꿈 및 기타 스크립트에 적대적인 문자가 포함될 수 있기 때문에 이것은 까다 롭습니다. find
파일 이름을 서로 안전하게 분리하고 사용하는 유일한 방법 -print0
은 널 문자로 분리 된 파일 이름을 인쇄하는 것을 사용 하는 것입니다. bash의 readarray
/ mapfile
함수가 null로 구분 된 문자열을 지원하지만 지원하지 않는 경우 이는 불편 하지 않습니다. Bash read
는 위의 루프로 연결됩니다.
[이 답변은 원래 2014 년에 작성되었습니다. 최신 버전의 bash가있는 경우 아래 업데이트를 참조하십시오.]
작동 원리
첫 번째 줄은 빈 배열을 만듭니다. array=()
read
명령문이 실행될 때마다 표준 입력에서 널로 구분 된 파일 이름을 읽습니다. 이 -r
옵션은 read
백 슬래시 문자를 그대로 두도록 지시 합니다. 은 -d $'\0'
지시 read
입력이 널 (null)로 구분 될 것이다. 에 이름을 생략 했으므로 read
쉘은 입력을 기본 이름 : REPLY
.
이 array+=("$REPLY")
명령문은 배열에 새 파일 이름을 추가합니다 array
.
마지막 줄은 리디렉션과 명령 대체를 결합 find
하여 while
루프 의 표준 입력에 대한 출력을 제공합니다 .
프로세스 대체를 사용하는 이유는 무엇입니까?
프로세스 대체를 사용하지 않았다면 루프는 다음과 같이 작성 될 수 있습니다.
array=()
find . -name "${input}" -print0 >tmpfile
while IFS= read -r -d $'\0'; do
array+=("$REPLY")
done <tmpfile
rm -f tmpfile
위의 출력은 find
임시 파일에 저장되며 해당 파일은 while 루프에 대한 표준 입력으로 사용됩니다. 프로세스 대체의 개념은 이러한 임시 파일을 불필요하게 만드는 것입니다. 따라서 while
루프가에서 stdin을 가져 오는 대신에서 stdin을 가져 오도록 tmpfile
할 수 있습니다 <(find . -name ${input} -print0)
.
프로세스 대체는 널리 유용합니다. 명령이 파일에서 읽으려는 많은 위치에서 <(...)
파일 이름 대신 프로세스 대체를 지정할 수 있습니다 . >(...)
명령이 파일 에 쓰려 는 파일 이름 대신 사용할 수 있는 유사한 형식 이 있습니다 .
배열과 마찬가지로 프로세스 대체는 bash 및 기타 고급 셸의 기능입니다. POSIX 표준의 일부가 아닙니다.
대안 : lastpipe
원하는 경우 lastpipe
프로세스 대체 대신 사용할 수 있습니다 (모자 팁 : Caesar ) :
set +m
shopt -s lastpipe
array=()
find . -name "${input}" -print0 | while IFS= read -r -d $'\0'; do array+=("$REPLY"); done; declare -p array
shopt -s lastpipe
bash는 현재 셸 (백그라운드 아님)의 파이프 라인에서 마지막 명령을 실행하도록 지시합니다. 이렇게 array
하면 파이프 라인이 완료된 후에도 남아 있습니다. lastpipe
작업 제어가 꺼진 경우에만 적용 되기 때문에 set +m
. (스크립트에서는 명령 줄과 달리 작업 제어가 기본적으로 꺼져 있습니다.)
추가 참고 사항
다음 명령은 셸 배열이 아닌 셸 변수를 만듭니다.
array=`find . -name "${input}"`
배열을 만들려면 find 출력 주위에 괄호를 넣어야합니다. 순진하게도 다음과 같이 할 수 있습니다.
array=(`find . -name "${input}"`)
문제는 쉘이의 결과에 대해 단어 분할을 수행 find
하여 배열의 요소가 원하는대로 보장되지 않는다는 것입니다.
2019 업데이트
버전 4.4-alpha부터 bash는 이제 -d
위의 루프가 더 이상 필요하지 않도록 옵션을 지원 합니다. 대신 다음을 사용할 수 있습니다.
mapfile -d $'\0' array < <(find . -name "${input}" -print0)
이에 대한 자세한 내용은 Benjamin W.의 답변을 참조하십시오 .