다음과 같은 작업을 하고 싶지만 파이프 끝 이후에 변수가 저장되지 않습니다.
fs=( )
echo ${fs[@]}
ls -A1 |
while read f
do
echo ${fs[@]}
fs+=( "$f" )
echo ${fs[@]}
done
echo "All files/dirs: "${fs[@]}
현재 디렉터리의 파일 1, 2, 3에 대해 다음과 같은 출력이 표시됩니다.
# Output:
1
1
1 2
1 2
1 2 3
All files/dirs:
파이프라인이 끝난 후 fs 변수의 값을 유지하는 방법은 무엇입니까?
고쳐 쓰다:
- 파일을 숨겨야 하므로 *를 사용할 수 없습니다.
- fs=($(ls)) 만 사용할 수 없으며 때로는 파일/디렉토리 이름에 공백이 있습니다.
답변1
쉘의 디렉토리에 있는 모든 파일을 나열하는 것은 간단합니다 *
.
for f in *; do …
배열(bash, ksh, zsh)을 지원하는 셸에서는 파일 목록을 배열 변수에 직접 할당할 수 있습니다.fs=(*)
이는 사용하기에 좋지 않은 도트 파일을 무시합니다 ls -A
. bash에서는 dotglob
먼저 도트 파일을 포함하도록 옵션을 설정하거나 nullglob
현재 디렉터리가 비어 있는 경우 빈 배열을 설정합니다.
shopt -s dotglob nullglob
fs=(*)
ksh에서는 를 사용합니다 FIGNORE=".?(.)"; fs=(~(N)*)
. zsh에서는 D
and N
glob 한정자를 사용합니다 fs=(*(DN))
. 다른 쉘에서는 이것이 더 어렵습니다. 가장 좋은 옵션은 각 패턴 *
(비 도트 파일), .[!.]*
(단일 도트 파일, 자체 제외 .
및 이중 도트 파일) 및 ..?*
(이중 도트 파일, ..
자체 제외)을 포함하는 것입니다 . 비어 있는.
set -- *; [ -e "$1" ] || shift
set .[!.]* "$@"; [ -e "$1" ] || shift
set ..?* "$@"; [ -e "$1" ] || shift
for x; do … # short for for x in "$@"; do …
귀하의 시도에 어떤 문제가 있는지 설명하는 것이 좋습니다. 주요 문제는 파이프의 각 끝이 하위 프로세스에서 실행되므로 fs
루프의 할당이 하위 프로세스에서 발생하고 상위 프로세스로 전달되지 않는다는 것입니다. (이것은 bash를 포함한 대부분의 쉘의 경우입니다. 두 가지 예외는 ATT ksh 및 zsh입니다. 여기서 파이프의 오른쪽은 상위 쉘에서 실행됩니다.) 외부 하위 프로세스를 시작하고 예약하여 이를 관찰할 수 있습니다. 해당 상위 인쇄 프로세스 ID1'2:
sh -c 'echo parent: $PPID'
{ sh -c 'echo left: $PPID >/dev/tty'; echo $? >/dev/null; } |
{ sh -c 'echo right: $PPID >/dev/tty'; echo $? >/dev/null; }
또한 코드에는 두 가지 안정성 문제가 있습니다.
- 출력을 구문 분석하지 마십시오
ls
. read
필요한 줄을 구문 분석하기 위해 공백과 백슬래시를 분리합니다.while IFS= read -r line; do …
실제로 행을 구문 분석하고 결과를 사용해야 하는 경우 전체 데이터 처리를 블록에 넣습니다.
producer … | {
while IFS= read -r line; do
…
done
consumer
}
1 아무것도 표시
하지 $$
않습니다. 이는 기본 셸 프로세스의 프로세스 ID이며 하위 셸에서는 변경되지 않습니다.
²
일부 bash 버전에서는 sh
bash가 외부 프로세스에 대한 호출을 최적화하기 때문에 파이프의 한쪽에서만 호출하면 동일한 프로세스 ID가 표시될 수 있습니다. 중괄호 보풀은 echo $?
이 최적화를 무효화합니다.
답변2
이 코드는 귀하의 요구 사항을 충족합니다 -
#!/bin/sh
echo *
도대체 여기서 무엇을 하고 싶나요?
너도 할 수 있어
var=*
echo $var
더 필요한 경우 stackoverflow로 이동하는 것이 좋습니다.
답변3
정말 튜브가 필요한가요? 이 작업은 쉽게 수행할 수 있습니다.
fs=( )
echo ${fs[@]}
for file in `ls`
do
echo $file
fs+=$file
done
echo $fs
echo "All files/dirs: "${fs[@]}