특정 디렉토리의 모든 파일을 bash 배열로 가져 오려고합니다 (이름에 줄 바꿈이없는 파일이 있다고 가정).
그래서:
myarr=()
find . -maxdepth 1 -name "mysqldump*" | mapfile -t myarr; echo "${myarr[@]}"
빈 결과!
파일을 사용하는 원형 교차로 방법을 사용하는 경우 임시 또는 다른 방법으로 :
myarr=()
find . -maxdepth 1 -name "mysqldump*" > X
mapfile -t myarray < X
echo "${myarray[@]}"
결과!
그런데 왜 mapfile
파이프에서 제대로 읽지 않습니까?
답변
보낸 사람 man 1 bash
:
파이프 라인의 각 명령은 별도의 프로세스 (즉, 서브 쉘)로 실행됩니다.
이러한 서브 쉘은 기본 쉘에서 변수를 상속하지만 독립적입니다. 이것은 mapfile
원래 명령에서 자체적으로 작동 한다는 것을 의미 합니다 myarr
. 그런 다음 echo
(파이프 외부에 있음) 빈 myarr
(메인 쉘 )을 인쇄합니다 myarr
.
이 명령은 다르게 작동합니다.
find . -maxdepth 1 -name "mysqldump*" | { mapfile -t myarr; echo "${myarr[@]}"; }
이 경우 mapfile
와 echo
동일한에서 작동 myarr
(하지의 주요 쉘이다 myarr
).
메인 쉘을 변경하려면 메인 쉘에서 정확하게 myarr
실행해야합니다 mapfile
. 예:
myarr=()
mapfile -t myarr < <(find . -maxdepth 1 -name "mysqldump*")
echo "${myarr[@]}"
답변
Bash는 서브 쉘 환경에서 파이프 라인의 명령을 실행하므로 그 안에서 발생하는 변수 할당 등은 쉘의 나머지 부분에 표시되지 않습니다.
zsh와 ksh는 기본 쉘에서 마지막 부분을 실행하는 반면 대시 (데비안 /bin/sh
)와 busybox sh
도 비슷합니다. Bash shopt -s lastpipe
에서도 동일한 작업을 수행 할 수 있지만 작업 제어가 비활성화 된 경우에만 작동하므로 기본적으로 대화식 쉘에서는 작동하지 않습니다.
그래서:
$ bash -c 'x=a; echo b | read x; echo $x'
a
$ bash -c 'shopt -s lastpipe; x=a; echo b | read x; echo $x'
b
( read
그리고 mapfile
같은 문제가 있습니다.)
또는 Attie가 언급 한대로 일반화 된 파이프처럼 작동하며 Bash, ksh 및 zsh에서 지원되는 프로세스 대체를 사용하십시오 .
$ bash -c 'x=a; read x < <(echo b); echo $x'
b
POSIX는 파이프 라인의 일부가 서브 쉘에서 실행되는지 여부를 지정하지 않은 상태로 두므로, 어떤 쉘도 이것에서 “잘못”되었다고 말할 수 없습니다.
답변
Kamil이 지적했듯이 파이프 라인의 각 요소는 별도의 프로세스입니다.
다음 프로세스 대체 를 사용 하여 현재 인터프리터에 호출이 남아 find
있는 다른 프로세스에서 실행 mapfile
하여 myarr
나중에 액세스 할 수 있습니다 .
myarr=()
mapfile -t myarr < <( find . -maxdepth 1 -name "mysqldump*" )
echo "${myarr[@]}"
b < <( a )
a | b
파이프 라인 연결 방식 과 유사하게 작동 합니다. 차이점은 b
” 여기 “에서 실행 됩니다 .