ls -l *의 차이점| wc -l 및 ls -l ||화장실-l

ls -l *의 차이점| wc -l 및 ls -l ||화장실-l

엄청난 양의 파일 목록이 포함된 폴더가 있는데 그 수를 세고 싶습니다. 나는 이것을 하고 있었고 ls -l *.json | wc -l명령이 더 이상 작동하지 않을 만큼 목록이 충분히 커질 때까지 잘 작동했습니다.

나중에 한 번 시도해 보았는데 ls -l | grep .json | wc -l정말 효과가 좋았습니다.

그럼 둘의 차이점이 무엇인지 알고 싶습니다. 후자가 ls모든 파일을 한 번에 처리하지 않고 지속적으로 스트리밍한 grep다음 wc? 그렇습니까, 아니면 다르게 작동합니까?

답변1

.json현재 디렉터리에서 확장명이 있는 숨겨지지 않은 파일의 수를 계산하려면 다음을 수행할 수 있습니다.

(){echo $#} *.json(NoN)

( N의 경우 nullglob여기서 oN필요하지 않은 정렬을 비활성화합니다).

ls -l | grep .json | wc -l이는 다음과 같은 여러 가지 이유로 잘못된 것입니다.

  • .단일 문자와 일치하는 정규식 연산자입니다. 또는 문자열을 검색하려는 경우 .json.grep -F .jsongrep '\.json'grep '[.]json'
  • 이는 Xjson각 행에서 검색됩니다. 를 사용하면 ls -l파일 이름, 사용자 이름, 그룹 이름, 심볼릭 링크 대상 등을 모두 포함할 수 있는 인쇄할 수 있습니다 Xjson.
  • 파일 이름에는 0과 of /(링크 대상에 포함될 수 있음 /)를 제외한 모든 바이트 값이 포함될 수 있습니다. 따라서 이름이 xjson\nyjson심볼릭 링크인 파일이 있으면 파일 은 모두 3줄을 인쇄합니다 . 일부 파일 이름에 현재 로케일 바이트 시퀀스에서 유효한 문자를 형성하지 ajson\nbjson않는 문자가 포함되어 있으면 놀랄 수도 있습니다.-qls -lXjson
  • grep | wc -l일반적으로 로 대체할 수 있습니다 grep -c.

ls -l *.json | wc -l더 나쁜. 옆에인수 목록이 너무 길면 잠재적인 문제가 발생할 수 있습니다.@L.ScottJohnson도 다음과 같이 지적했습니다.

  • 숨겨지지 않은 파일이 없으면 glob을 일치시킬 수 없기 때문에 오류가 .json발생합니다 .0zsh*.json
  • 각 매개변수 유형에 대해목차, ls -l해당 내용을 나열하므로 디렉토리가 있는 경우 dir.json해당 목록의 모든 행이 계산됩니다. 일반적으로 -dglob 확장을 에 전달할 때 a를 사용 하려고 합니다 ls.
  • .json파일 이름이 로 시작하는 경우 -해당 파일 이름은 옵션으로 처리됩니다 (특히 옵션이 아닌 인수 이후에도 옵션을 허용하는 lsGNU 또는 비지박스 구현 ).ls
  • 위에서 언급한 것처럼 파일 이름이나 기호 링크 대상에 개행 문자가 포함되어 있으면 문제가 발생합니다.

다음 방법을 사용하여 대부분의 문제를 해결할 수 있습니다.

LC_ALL=C ls -qd -- *.json | wc -l

그러나 실제 작업은 모두 쉘에서 수행됩니다. shell은 *.json파일 목록과 일치하여 에 전달하는 확장입니다 ls. ls입력을 위해 각 파일을 별도의 줄에 인쇄하여 wc계산할 수 있습니다. 또한 존재 여부를 확인하기 위해 각각에 시스템 호출을 하는 ls것과 같은 불필요한 작업을 많이 수행하고 ( 사용자/그룹 이름 확인을 위해 a 및 일부 uid/gid를 수행하고 심볼릭 링크를 위해 s를 사용) 목록이 정렬됩니다( 쉘은 이미 확장자를 정렬합니다).stat()-llstat()readlink()*.json

쉘은 이 확장을 자체적으로 잘 계산합니다.

의 경우 (){echo $#} *.json(NoN)익명 함수를 사용하며 임시 배열을 사용할 수도 있습니다 files=(*.json(NoN)); echo $#files.

또한읽다ls목록을 작성하기 위해 현재 디렉토리의 내용을 사용하므로 이전처럼 각 파일을 개별적으로 찾을 필요가 없습니다 .

이 구문은 구체적입니다 zsh. POSIX의 해당 구문은 sh다음과 유사합니다.

set -- [*].json *.json
case $1$2 in
  ('[*].json*.json') shift 2;;
  (*) shift;;
esac
echo "$#"

(파일 목록은 "$@"(정렬)에 있습니다.)

답변2

확장된 파일 목록이 너무 길면 파일 목록을 확장하기 위해 셸을 사용하기 때문에 원래 명령이 실패할 수 있습니다.

ls -l | grep .json | wc -l 

문제 없습니다. 명령줄은 짧고(확장 없음) grep은 한 줄씩 필터링하기 때문입니다.

점은 점뿐만 아니라 모든 문자와 일치합니다. 고정 문자열에는 -F를 사용하십시오.

ls -l | grep -F .json | wc -l 

xjson이렇게 하면 실수로 파일을 일치시키 거나 그와 같은 어리석은 일이 발생하지 않습니다 .

명령에 대한 몇 가지 주의 사항과 의도한 목표를 달성하기 위한 다른 (보다 강력한) 방법이 여전히 있지만 이러한 문제 외에는 파일 이름 와일드카드(예: 셸 확장자)로 필터링하는 것과 파이프라는 두 명령의 차이점이 있습니다. -to-grep

관련 정보