공백 + 변수가 있는 L

공백 + 변수가 있는 L

다음과 같은 작업을 하고 싶지만 파이프 끝 이후에 변수가 저장되지 않습니다.

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

출력을 구문 분석하지 마십시오 ls.

쉘의 디렉토리에 있는 모든 파일을 나열하는 것은 간단합니다 *.

for f in *; do …

배열(bash, ksh, zsh)을 지원하는 셸에서는 파일 목록을 배열 변수에 직접 할당할 수 있습니다.fs=(*)

이는 사용하기에 좋지 않은 도트 파일을 무시합니다 ls -A. bash에서는 dotglob먼저 도트 파일을 포함하도록 옵션을 설정하거나 nullglob현재 디렉터리가 비어 있는 경우 빈 배열을 설정합니다.

shopt -s dotglob nullglob
fs=(*)

ksh에서는 를 사용합니다 FIGNORE=".?(.)"; fs=(~(N)*). zsh에서는 Dand Nglob 한정자를 사용합니다 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; }

또한 코드에는 두 가지 안정성 문제가 있습니다.

실제로 행을 구문 분석하고 결과를 사용해야 하는 경우 전체 데이터 처리를 블록에 넣습니다.

producer … | {
  while IFS= read -r line; do
  done
  consumer
}

1 아무것도 표시 하지 $$않습니다. 이는 기본 셸 프로세스의 프로세스 ID이며 하위 셸에서는 변경되지 않습니다.
² 일부 bash 버전에서는 shbash가 외부 프로세스에 대한 호출을 최적화하기 때문에 파이프의 한쪽에서만 호출하면 동일한 프로세스 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[@]}

관련 정보