sed와 wc를 awk로 바꾸는 방법은 무엇입니까? (디렉토리의 이름 계산)

sed와 wc를 awk로 바꾸는 방법은 무엇입니까? (디렉토리의 이름 계산)

폴더 내부의 요소 수를 계산하고 싶습니다. 나는 그것에 대해 생각했다

function lsc { /bin/ls -l $1 | sed 1d | wc -l }

그러나 나는 사람들이 어떻게 이 파이프들을 줄이고 여분의 것들을 awk제거하고 있는지 기억해냈습니다 . 그래서 당신은 무엇을 합니까 ?grepsedawk

답변1

ls, sed또는 wc가 필요하지 않습니다 awk.

패턴이 확장되는 이름의 수를 세고 싶다면 다음을 사용할 수 있습니다.

set -- *
echo "$#"

set명령은 위치 인수( 등)를 패턴 과 일치하는 이름 $1으로 설정합니다 . 이는 자동으로 특수 변수를 설정된 위치 인수 수, 즉 주어진 패턴과 일치하는 이름 수로 설정합니다.$2*$#

bash명명된 배열이 있는 셸 에서는 다음을 사용할 수 있습니다.

names=(*)
echo "${#names[@]}"

이는 유사하게 작동하지만 배열의 요소를 names패턴 확장에 의해 생성된 이름으로 설정합니다 *. 변수 확장은 ${#names[@]}배열의 요소 수입니다 names.

이에 대한 한 가지 문제는 패턴이 아무것도 일치하지 않으면 확장되지 않은 상태로 유지되므로 개수가 1이라는 것입니다(디렉토리가 비어 있는 경우에도). 쉘에서 이 문제를 해결하려면 bashnullglob쉘 옵션을 설정하십시오 shopt -s nullglob. 이 쉘 옵션을 설정하면 어떤 것과도 일치하지 않는 패턴이 완전히 제거됩니다.

에서 bash숨겨진 이름의 수도 계산하려면 dotglob으로 쉘 옵션을 설정하십시오 shopt -s dotglob.

bash귀하의 기능은 다음 과 같습니다

lsc () (
    shopt -s nullglob
    set -- "$1"/*
    echo "$#"
)

( ... )nullglob호출 셸에서 설정 하지 않도록 함수 본문에서 사용하도록 주의하세요 .

또는 다음의 경우 /bin/sh:

lsc () {
    set -- "$1"/*
    if [ -e "$1" ] || [ -L "$1" ]; then
        echo "$#"
    else
        echo 0
    fi
}

여기의 명령문은 if첫 번째 위치 인수가 (아무것도 일치하지 않기 때문에) 확장되지 않은 패턴이 아니라 실제 파일의 이름임을 보장합니다. ( -e"exists")는 우리가 의 숫자를 신뢰하기 위해 참이어야 합니다 $#. 잘못된 경우 이름이 테스트의 심볼릭 링크를 참조하는지 확인합니다 -L. 이것이 사실이라면 패턴이 확장되는 첫 번째 것은 "죽은" 심볼릭 링크(존재하지 않는 파일을 가리키는 심볼릭 링크)라는 것을 알고 $#그것이 정확하다고 믿습니다. 두 테스트가 모두 실패하면 일치하는 항목이 없다는 것을 알 수 있으므로 출력은 입니다 0.

답변2

첫째, 한 줄짜리 함수 정의가 올바르지 않습니다. 이 키워드가 있다는 것은 아마도 Bash를 사용하고 있음을 나타냅니다. 이것은 functionman bash에 있는 것입니다:Shell Function Definitions

function name [()] compound-command [redirection]

그리고복합 명령로써 정의 된:

{ list; }

따라서 다음과 같아야 합니다.

function lsc { /bin/ls -l $1 | sed 1d | wc -l; }

하지만 기술적으로 정확하더라도 잘 작동하지는 않습니다. 아니요구문 분석 ls(및 수행 방법)?.

다음과 같이 awk를 사용하여 특정 디렉터리에 있는 여러 파일과 디렉터리를 인쇄할 수 있습니다.

awk 'END {print ARGC - 1}' *

그러나 *awk는 쉘 확장에 대한 인수 중 하나 이상이 디렉토리인 경우 오류를 표시합니다.

$ awk 'END {print ARGC - 1}' *
awk: warning: command line argument `dir1' is a directory: skipped

그러나 어쨌든 결과는 여전히 좋습니다. 오류를 /dev/null로 리디렉션할 수 있습니다.

awk 'END {print ARGC - 1}' * 2>/dev/null

관련 정보