[bash] 파일을 세는 bash 명령이 있습니까?

패턴과 일치하는 파일 수를 계산하는 bash 명령이 있습니까?

예를 들어,이 패턴과 일치하는 디렉토리의 모든 파일 수를 가져오고 싶습니다. log*



답변

이 간단한 단일 라이너는 bash뿐만 아니라 모든 쉘에서 작동해야합니다.

ls -1q log* | wc -l

ls -1q는 공백이나 개행과 같은 특수 문자가 포함되어 있어도 파일 당 한 줄을 제공합니다.

출력은 행 수를 계산하는 wc -l로 파이프됩니다.


답변

\nbash를 사용 하여 안전하게 할 수 있습니다 (즉, 공백이 있거나 파일 이름 이 버그로 표시되지 않음 ).

$ shopt -s nullglob
$ logfiles=(*.log)
$ echo ${#logfiles[@]}

일치하는 파일이없는 경우 배열nullglob 에서 리터럴 *.log을 얻지 않도록 활성화해야합니다 . 안전하게 재설정하는 방법에 대한 예 는 ‘set -x’를 “실행 취소하는 방법”을 참조하십시오 .$logfiles


답변

여기에 많은 답변이 있지만 일부는 고려하지 않습니다.

  • 공백, 개행 또는 제어 문자가 포함 된 파일 이름
  • 하이픈으로 시작하는 파일 이름 (이라는 파일을 상상해보십시오 -l)
  • 글로브가 있다면 (점으로 시작하는 숨겨진 파일, *.log대신log*
  • 글로브와 일치하는 디렉토리 (예 : 디렉토리라는 logs일치 log*)
  • 빈 디렉토리 (예 : 결과는 0)
  • 매우 큰 디렉토리 (모두 나열하면 메모리가 소모 될 수 있음)

다음은 이들 모두를 처리하는 솔루션입니다.

ls 2>/dev/null -Ubad1 -- log* | wc -l

설명:

  • -U원인 ls을 의미하지 정렬 항목으로는 메모리에 목록 전체 디렉토리를로드 할 필요가 없습니다
  • -b그래픽이 아닌 문자에 대해 C 스타일 이스케이프를 인쇄하여 줄 바꿈이로 인쇄되도록 \n합니다.
  • -a숨겨진 파일을 포함하여 모든 파일을 인쇄합니다 (glob log*가 숨겨진 파일을 암시하지 않을 때 반드시 필요하지는 않음 )
  • -d목록에 시도하지 않고 디렉토리 밖으로 인쇄 내용이 무엇 디렉토리의 ls일반적으로 할 것을
  • -1 하나의 열에 있는지 확인하십시오 (ls는 파이프에 쓸 때 자동으로 수행하므로 반드시 필요한 것은 아닙니다)
  • 2>/dev/null로그 파일이 0 개이면 오류 메시지를 무시하도록 stderr를 리디렉션합니다. (주 shopt -s nullglob원인이 ls아니라 전체 작업 디렉토리를 나열합니다.)
  • wc -l디렉토리 목록이 생성 될 때 디렉토리 목록을 사용하므로 출력은 ls어느 시점에서나 메모리에 저장되지 않습니다.
  • --파일 이름은 --인수로 이해되지 않도록 사용하여 명령과 분리 됩니다 ls( log*제거 된 경우 ).

log* 전체 파일 목록으로 확장 되므로 파일이 많으면 메모리가 소모 될 수 있으므로 grep을 통해 실행하는 것이 좋습니다.

ls -Uba1 | grep ^log | wc -l

이 마지막 것은 많은 메모리를 사용하지 않고 (서브 쉘을 사용하더라도) 매우 큰 파일 디렉토리를 처리합니다. 는 -d단지 현재 디렉토리의 내용을 나열 있기 때문에, 더 이상 필요하지 않습니다.


답변

재귀 검색의 경우 :

find . -type f -name '*.log' -printf x | wc -c

wc -c의 출력에서 ​​문자 수를 계산하는 find동안 각 결과에 대해 단일 문자 를 인쇄하도록 -printf x지시 find합니다 x.

비재 귀적 검색의 경우 다음을 수행하십시오.

find . -maxdepth 1 -type f -name '*.log' -printf x | wc -c


답변

이 질문에 대한 답변이 잘못되었지만 담당자가 적으므로 의견을 추가 할 수 없습니다.

이 질문에 대한 정답은 Mat가 제공합니다.

shopt -s nullglob
logfiles=(*.log)
echo ${#logfiles[@]}

허용되는 대답의 문제점은 wc -l이 줄 바꾸기 문자 수를 계산하고 터미널에 ‘?’로 인쇄하더라도 문자 수를 계산한다는 것입니다. ‘ls -l’의 출력에서. 이는 파일 이름에 줄 바꿈 문자가 포함 된 경우 허용 된 답변이 실패 함을 의미합니다. 제안 된 명령을 테스트했습니다.

ls -l log* | wc -l

이름에 개행 문자가 포함 된 패턴과 일치하는 파일이 하나 뿐인 경우에도 2의 값을 잘못보고합니다. 예를 들면 다음과 같습니다.

touch log$'\n'def
ls log* -l | wc -l


답변

파일이 많고 우아 shopt -s nullglob하고 bash 배열 솔루션 을 사용하지 않으려면 파일 이름을 인쇄하지 않는 한 찾기 등을 사용할 수 있습니다 (줄 바꿈 포함).

find -maxdepth 1 -name "log*" -not -name ".*" -printf '%i\n' | wc -l

log *와 일치하고 다음으로 시작하지 않는 모든 파일을 찾습니다 .*. “not name. *”는 중복되지만 “ls”의 기본값은 도트 파일을 표시하지 않지만 기본값은 점입니다. 찾기 위해 그들을 포함하는 것입니다.

이것은 정답이며 파일 이름이 명령 사이에 전달되지 않기 때문에 던질 수있는 모든 유형의 파일 이름을 처리합니다.

그러나 shopt nullglob답이 가장 좋습니다!


답변

여기에 하나의 라이너가 있습니다.

 file_count=$( shopt -s nullglob ; set -- $directory_to_search_inside/* ; echo $#)