루프 출력용 파이핑으로 로컬 변수 수정 방지


11

인수로 많은 파일 및 / 또는 디렉토리를 취하는 간단한 bash 함수를 작성하려고합니다. 다음과 같아야합니다.

  1. 파일 이름을 완전히 규정하십시오.
  2. 그것들을 정렬하십시오.
  3. 중복을 제거하십시오.
  4. 실제로 존재하는 모든 것을 인쇄하십시오.
  5. 존재하지 않는 파일 수를 반환합니다.

나는 내가 원하는 것을 거의 수행하지만 정렬에 빠지는 스크립트가 있습니다. 스크립트의 반환 값은 정확하지만 출력이 정렬되지 않고 복제되지 않습니다. | sort -u표시된대로 명령문의 주석을 해제하면 출력은 정확하지만 리턴 값은 항상 0입니다.

NB 문제를 해결하기위한 간단한 솔루션은 환영하지만 실제로 내가 가진 코드에서 이것이 왜 발생하는지에 대한 질문입니다. 즉, 파이프를 추가하면 스크립트가 변수 증가를 중지하는 것처럼 보이는 이유는 r무엇입니까?

스크립트는 다음과 같습니다.

function uniqfile
{
    local r=0 

    for arg in "$@"
    do  
        readlink -e "$arg" || (( ++r ))

    done #| sort -u    ## remove that comment

    return $r
}

작은 관찰입니다. 당신은 줄일 수 있습니다 for arg in "$@"for arg. " 'WORDS에서 ...;' 이 없으면 'in $ "로 가정합니다." -도움말
manatwork

답변:


15

기능 으로 인해 잘 알려진 bash 함정입니다 .

파이프 라인의 각 명령은 별도의 프로세스 (즉, 서브 쉘)로 실행됩니다.

수정 된 변수는 서브 쉘에 국한되며 상위에서 다시 표시되지 않습니다.

이를 피하려면 프로세스 대체를 사용하여 파이프 라인을 피하도록 코드를 바꾸십시오.

 for arg in "$@"
    do  
        readlink -e "$arg" || (( ++r ))

    done > >(sort -u)

감사합니다. 훌륭합니다. 나는 당신이 >(..command..)구조물 의 이름을 말해 줄 수 있는지 궁금합니다 . 나는 그것이 어떻게 작동하는지 알고 있지만 더 읽어야한다고 생각합니다.
tjm

2
@tjm :가 호출 프로세스 대체
enzotib

Bash에서의 프로세스 대체는 다음과 같은 많은 형태를 가진다 : tldp.org/LDP/abs/html/process-sub.html
slm

프로세스 대체 는 명령의 입력 또는 출력을 파일로 표시 할 수있는 프로세스 간 통신 형식입니다. 명령은 파일 이름이 일반적으로 발생 하는 명령행으로 인라인으로 대체됩니다. 이를 통해 일반적으로 파일 만 허용하는 프로그램이 다른 프로그램에서 직접 읽거나 쓸 수 있습니다.
nobar

3

| sort -u앞의 비트 (루프 전체 때문에) 하위 프로세스에서 실행하는 힘 (bash는은으로 리디렉션하는 'STDOUT을'필요 sort'STDIN'. (인터넷이 생각하는 것 ksh하고 bash첫 번째 또는 마지막 약간 다르게 ..이 사건을 처리 파이프 시퀀스의 명령이 하위 셸에 배치됩니까?)

이 스레드는 비슷한 문제를 겪고 있으며 끝에 깔끔한 솔루션이 있습니다. http://ubuntuforums.org/showthread.php?t=312017

발췌
    #!/bin/bash
    exec 3< <(du | sort -n)  

    n=0
    while read size dir; do
      [ $size -gt 1000 ] && ((n++))
    done <&3
    exec 3<&-

    echo "Found $n too big files"
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.