파일을 세는 bash 명령이 있습니까?
패턴과 일치하는 파일 수를 계산하는 bash 명령이 있습니까?
예를 들어,이 패턴과 일치하는 디렉토리의 모든 파일 수를 가져오고 싶습니다. log*
이 간단한 단일 라이너는 bash뿐만 아니라 모든 쉘에서 작동해야합니다.
ls -1q log* | wc -l
ls -1q는 공백이나 개행과 같은 특수 문자가 포함되어 있어도 파일 당 한 줄을 제공합니다.
출력은 행 수를 계산하는 wc -l로 파이프됩니다.
\n
bash를 사용 하여 안전하게 할 수 있습니다 (즉, 공백이 있거나 파일 이름 이 버그로 표시되지 않음 ).
$ 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
숨겨진 파일을 포함하여 모든 파일을 인쇄합니다 (globlog*
가 숨겨진 파일을 암시하지 않을 때 반드시 필요하지는 않음 )-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' | wc -l
wc -w
출력의 단어 수를 계산합니다 (bash는 *.log
해당 패턴과 일치하는 공백으로 구분 된 파일 목록으로 확장 됨 ). 줄 wc -l
수는 계산합니다 ( find
한 줄에 하나의 결과를 인쇄 함).
비재 귀적 검색의 경우 다음을 수행하십시오.
find . -maxdepth 1 -type f -name '*.log' | wc -l
이 질문에 대한 답변이 잘못되었지만 담당자가 적으므로 의견을 추가 할 수 없습니다.
이 질문에 대한 정답은 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
If you have a lot of files and you don't want to use the elegant shopt -s nullglob
and bash array solution, you can use find and so on as long as you don't print out the file name (which might contain newlines).
find -maxdepth 1 -name "log*" -not -name ".*" -printf '%i\n' | wc -l
This will find all files that match log* and that don't start with .*
— The "not name .*" is redunant, but it's important to note that the default for "ls" is to not show dot-files, but the default for find is to include them.
This is a correct answer, and handles any type of file name you can throw at it, because the file name is never passed around between commands.
But, the shopt nullglob
answer is the best answer!
Here is my one liner for this.
file_count=$( shopt -s nullglob ; set -- $directory_to_search_inside/* ; echo $#)
You can use the -R option to find the files along with those inside the recursive directories
ls -R | wc -l // to find all the files
ls -R | grep php | wc -l // to find the files which contains the word php
you can use patterns on the grep
You can define such a command easily, using a shell function. This method does not require any external program and does not spawn any child process. It does not attempt hazardous ls
parsing and handles “special” characters (whitespaces, newlines, backslashes and so on) just fine. It only relies on the file name expansion mechanism provided by the shell. It is compatible with at least sh, bash and zsh.
The line below defines a function called count
which prints the number of arguments with which it has been called.
count() { echo $#; }
Simply call it with the desired pattern:
count log*
For the result to be correct when the globbing pattern has no match, the shell option nullglob
(or failglob
— which is the default behavior on zsh) must be set at the time expansion happens. It can be set like this:
shopt -s nullglob # for sh / bash
setopt nullglob # for zsh
Depending on what you want to count, you might also be interested in the shell option dotglob
.
Unfortunately, with bash at least, it is not easy to set these options locally. If you don’t want to set them globally, the most straightforward solution is to use the function in this more convoluted manner:
( shopt -s nullglob ; shopt -u failglob ; count log* )
If you want to recover the lightweight syntax count log*
, or if you really want to avoid spawning a subshell, you may hack something along the lines of:
# sh / bash:
# the alias is expanded before the globbing pattern, so we
# can set required options before the globbing gets expanded,
# and restore them afterwards.
count() {
eval "$_count_saved_shopts"
unset _count_saved_shopts
echo $#
}
alias count='
_count_saved_shopts="$(shopt -p nullglob failglob)"
shopt -s nullglob
shopt -u failglob
count'
As a bonus, this function is of a more general use. For instance:
count a* b* # count files which match either a* or b*
count $(jobs -ps) # count stopped jobs (sh / bash)
By turning the function into a script file (or an equivalent C program), callable from the PATH, it can also be composed with programs such as find
and xargs
:
find "$FIND_OPTIONS" -exec count {} \+ # count results of a search
ls -1 log* | wc -l
Which means list one file per line and then pipe it to word count command with parameter switching to count lines.
Here's what I always do:
ls log* | awk 'END{print NR}'
참고URL : https://stackoverflow.com/questions/11307257/is-there-a-bash-command-which-counts-files
'programing tip' 카테고리의 다른 글
XOR이 해시를 결합하는 기본 방법 인 이유는 무엇입니까? (0) | 2020.06.27 |
---|---|
ASP.NET 웹 API에서 다운로드 파일 이름을 설정하는 방법 (0) | 2020.06.27 |
Angular 2의 로컬 스토리지 (0) | 2020.06.27 |
Java에서 링크 된 목록 데이터 구조를 작성하는 방법 (0) | 2020.06.27 |
파이썬 : 출력 문자열 형식, 오른쪽 정렬 (0) | 2020.06.27 |