파일을 세는 bash 명령어가 있습니까?
패턴과 일치하는 파일 수를 세는 bash 명령어가 있습니까?
를 들어,이 과 일치하는 의 수를 : 예 들 어 다 패 수 가 고 려 합 오 니 져 다 를 파 를 일 모 든 의 리 음 터 디 는 렉 턴 일 하 치 과 ▁for 다log*
이 간단한 원라이너는 bash뿐만 아니라 모든 셸에서 작동해야 합니다.
ls -1q log* | wc -l
ls -1q는 공백이나 새 줄과 같은 특수 문자를 포함하더라도 파일당 한 줄을 제공합니다.
출력은 wc -l로 파이프 연결되어 라인 수를 계산합니다.
여기에는 많은 답이 있지만, 일부는 고려하지 않습니다.
- 공백, 줄 바꿈 또는 제어 문자가 있는 파일 이름
- (" ▁called▁file(▁file이)▁a포▁thathens▁(imagine
-l) - 파일숨진파일지, 점시는파일하작경우겨있으는이구본로지▁the,▁hidden파(일)▁files경,if우▁(▁dot있
*.log에log* - ▁directory()리ies▁that▁director리토토디▁the디렉▁(▁glob)
logs일치하는log*) - 빈 디렉토리(즉, 결과는 0)
- 매우 큰 디렉토리(모두 메모리를 소모할 수 있음)
다음은 이러한 모든 문제를 해결하는 솔루션입니다.
ls 2>/dev/null -Ubad1 -- log* | wc -l
설명:
-U인들원ls, 즉에 전체 가 없음을 합니다.-b이 아닌 문자에 대해 C 이스케이프를 으로 새 이 비래픽문대한자 C이스프인다를로 됩니다. 결정적으로 새 줄이 인쇄되도록 합니다.\n.-a모든 파일, 심지어 숨긴 파일도 출력합니다(글로벌할 때 엄격하게 필요하지 않음).log*숨김 파일 없음)-d디렉토리의 내용을 나열하지 않고 디렉토리를 인쇄합니다.ls보통이라면 할 수 있을 것-1하나의 열에 있는지 확인합니다(ls는 파이프에 쓸 때 자동으로 이 작업을 수행하므로 엄격하게 필요하지 않습니다).2>/dev/null로그 인 경우 메시지를 . stderr은 0개의 로그 파일을 무시합니다 (: (으)로 표시: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
작업은 안전하게 할 수 공백이 이나 이작을안게전수하있다수. 즉, 있파일이나는니공습백이할행).\n그들의 이름으로) bash:
$ shopt -s nullglob
$ logfiles=(*.log)
$ echo ${#logfiles[@]}
문자 그대로 사용할 수 없도록 설정해야 합니다.*.log에 시대에$logfiles 일치하는 파일이 없는 경우 배열. (안전하게 재설정하는 방법에 대한 예는 'set -x'를 "실행 취소"하는 방법을 참조하십시오.)
이 질문에 대한 수락된 답변은 틀리지만, 저는 낮은 평가를 받고 있기 때문에 코멘트를 추가할 수 없습니다.
이 질문에 대한 정답은 매트가 제공합니다.
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
중요한 논평
(평판이 부족하여 논평할 수 없음)
BUGGY입니다.
ls -1q some_pattern | wc -l
한다면shopt -s nullglob우연히 설정되면 패턴이 있는 파일뿐만 아니라 모든 일반 파일의 수를 출력합니다(CentOS-8 및 Cygwin에서 테스트됨).다른 무의미한 벌레들이 무엇을 하는지 누가 압니까?ls가지고 계십니까?
이것은 정확하고 훨씬 빠릅니다.
shopt -s nullglob; files=(some_pattern); echo ${#files[@]};
그것은 예상되는 일을 합니다.
And the running times differ.
The 1st:
0.006 on CentOS, and
0.083 on Cygwin (in case it is used with care).
The 2nd:
0.000 on CentOS, and
0.003 on Cygwin.
파일이 많고 우아한 파일을 사용하지 않으려는 경우shopt -s nullglobbash 어레이 솔루션을 사용하면 파일 이름(새 줄이 포함될 수 있음)을 출력하지 않는 한 find 등이 포함될 수 있음).
find -maxdepth 1 -name "log*" -not -name ".*" -printf '%i\n' | wc -l
하면 log하며 "*"로 됩니다..*"이름이 아닙니다.는 중복되지만 "ls"에 대한 기본값은 점 파일을 표시하지 않는 것이지만 찾기 기본값은 점 파일을 포함하는 것입니다.
파일 이름은 명령 간에 전달되지 않기 때문에 이는 올바른 대답이며, 사용자가 던질 수 있는 모든 유형의 파일 이름을 처리합니다.
그데그런.shopt nullglob답은 최고의 답입니다!
여기 이것을 위한 나의 하나의 라이너입니다.
file_count=$( shopt -s nullglob ; set -- $directory_to_search_inside/* ; echo $#)
셸 함수를 사용하여 이러한 명령을 쉽게 정의할 수 있습니다.이 메서드는 외부 프로그램이 필요하지 않으며 하위 프로세스를 생성하지 않습니다.은 위험한 일을 .ls"특수" 문자(공백, 줄 바꿈, 백슬래시 등)를 구문 분석하고 처리합니다.셸에서 제공하는 파일 이름 확장 메커니즘에만 의존합니다.적어도 sh, bash 및 zsh와 호환됩니다.
은 아라인다음같함정은다의니합수를라고 하는 합니다.count호출된 인수의 수를 출력합니다.
count() { echo $#; }
원하는 패턴을 사용하여 간단히 호출:
count log*
때 셸 " " " " " " " " " " " " " " " " " 이 .nullglob(또는)failglob에서 기본 .zsh)에서 할 때 .다음과 같이 설정할 수 있습니다.
shopt -s nullglob # for sh / bash
setopt nullglob # for zsh
셀 항목에 따라 셸 옵션에도 관심이 있을 수 있습니다.dotglob.
유감스럽게도 최소한 bash를 사용하면 이러한 옵션을 로컬로 설정하는 것이 쉽지 않습니다.이러한 설정을 전체적으로 설정하지 않으려면 가장 간단한 해결 방법은 다음과 같이 복잡한 방식으로 기능을 사용하는 것입니다.
( shopt -s nullglob ; shopt -u failglob ; count log* )
구문을 Lightweight 구려는경우하문구복을경▁if우▁thecount log*또는 하위 셸이 생성되지 않도록 하려면 다음과 같이 해킹할 수 있습니다.
# 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'
추가적으로, 이 기능은 더 일반적으로 사용됩니다.예를 들어:
count a* b* # count files which match either a* or b*
count $(jobs -ps) # count stopped jobs (sh / bash)
파일 이와 C 프로그램)로하여 ""와 .find그리고.xargs:
find "$FIND_OPTIONS" -exec count {} \+ # count results of a search
-R 옵션을 사용하여 재귀 디렉터리에 있는 파일과 함께 파일을 찾을 수 있습니다.
ls -R | wc -l // to find all the files
ls -R | grep log | wc -l // to find the files which contains the word log
당신은 그렙의 패턴을 사용할 수 있습니다.
저는 이 대답에 대해 많은 생각을 했습니다. 특히 파서하지 않는 것들을 고려했을 때 말입니다.처음에 저는 노력했습니다.
<경고! 작동하지 않음>
du --inodes --files0-from=<(find . -maxdepth 1 -type f -print0) | awk '{sum+=int($1)}END{print sum}'
</경고! 작동하지 않음>
같은 파일 이름만 있으면 작동했습니다.
touch $'w\nlf.aa'
이렇게 파일 이름을 만들면 실패합니다.
touch $'firstline\n3 and some other\n1\n2\texciting\n86stuff.jpg'
저는 마침내 제가 아래에 두고 있는 것을 생각해냈습니다.참고 디렉터리(하위 디렉터리 제외)에 있는 모든 파일의 개수를 가져오려고 했습니다.저는 @Mat과 @Dan_Yard의 답변과 함께 @mogsie에 의해 설정된 요구 사항의 대부분을 가지고 있다고 생각합니다(기억력에 대해서는 잘 모르겠습니다).저는 @mogsie의 답이 옳다고 생각하지만, 저는 항상 구문 분석을 멀리하려고 노력합니다.ls아주 구체적인 상황이 아니라면요
awk -F"\0" '{print NF-1}' < <(find . -maxdepth 1 -type f -print0) | awk '{sum+=$1}END{print sum}'
더 읽기 쉽게:
awk -F"\0" '{print NF-1}' < \
<(find . -maxdepth 1 -type f -print0) | \
awk '{sum+=$1}END{print sum}'
이것은 특히 파일을 찾기 위해 공백 및 줄바꿈 문제를 피하기 위해 출력을 null 문자로 구분한 다음 null 문자 수를 계산합니다.파일 수는 끝에 null 문자가 있으므로 null 문자 수보다 1개 적습니다.
OP의 질문에 답하기 위해 고려해야 할 두 가지 경우가 있습니다.
비재귀적 검색:
awk -F"\0" '{print NF-1}' < \
<(find . -maxdepth 1 -type f -name "log*" -print0) | \
awk '{sum+=$1}END{print sum}'
재귀 검색입니다.로 내에있것 안에 것은 무엇입니까?-name약간 다른 동작(숨겨진 파일 등)에 대해 매개 변수를 변경해야 할 수 있습니다.
awk -F"\0" '{print NF-1}' < \
<(find . -type f -name "log*" -print0) | \
awk '{sum+=$1}END{print sum}'
제가 이 답변에서 언급한 것과 비교하여 이 답변에 대해 의견을 제시하고 싶은 사람이 있다면 말씀해 주십시오.
참고로, 저는 이 답을 얻으면서 이 생각의 과정에 도달했습니다.
이것은 표준 POSIX 셸 문법으로 수행할 수 있습니다.
여기 간단한 것이 있습니다.count_entries함수:
#!/usr/bin/env sh
count_entries()
{
# Emulating Bash nullglob
# If argument 1 is not an existing entry
if [ ! -e "$1" ]
# argument is a returned pattern
# then shift it out
then shift
fi
echo $#
}
콤팩트한 정의의 경우:
count_entries(){ [ ! -e "$1" ]&&shift;echo $#;}
유형별 POSIX 호환 파일 카운터:
#!/usr/bin/env sh
count_files()
# Count the file arguments matching the file operator
# Synopsys:
# count_files operator FILE [...]
# Arguments:
# $1: The file operator
# Allowed values:
# -a FILE True if file exists.
# -b FILE True if file is block special.
# -c FILE True if file is character special.
# -d FILE True if file is a directory.
# -e FILE True if file exists.
# -f FILE True if file exists and is a regular file.
# -g FILE True if file is set-group-id.
# -h FILE True if file is a symbolic link.
# -L FILE True if file is a symbolic link.
# -k FILE True if file has its `sticky' bit set.
# -p FILE True if file is a named pipe.
# -r FILE True if file is readable by you.
# -s FILE True if file exists and is not empty.
# -S FILE True if file is a socket.
# -t FD True if FD is opened on a terminal.
# -u FILE True if the file is set-user-id.
# -w FILE True if the file is writable by you.
# -x FILE True if the file is executable by you.
# -O FILE True if the file is effectively owned by you.
# -G FILE True if the file is effectively owned by your group.
# -N FILE True if the file has been modified since it was last read.
# $@: The files arguments
# Output:
# The number of matching files
# Return:
# 1: Unknown file operator
{
operator=$1
shift
case $operator in
-[abcdefghLkprsStuwxOGN])
for arg; do
# If file is not of required type
if ! test "$operator" "$arg"; then
# Shift it out
shift
fi
done
echo $#
;;
*)
printf 'Invalid file operator: %s\n' "$operator" >&2
return 1
;;
esac
}
count_files "$@"
사용 예:
count_files -f log*.txt
count_files -d datadir*
루프가 없는 대체 디렉터리가 아닌 항목 수:
#!/bin/sh
# Creates strings of as many dots as expanded arguments
# dotted string for entries matching star pattern
star=$(printf '%.0s.' ./*)
# dotted string for entries matching star slash pattern (directories)
star_dir=$(printf '%.0s.' ./*/)
# dotted string for entries matching dot star pattern
dot_star=$(printf '%.0s.' ./.*)
# dotted string for entries matching dot star slash pattern (directories)
dot_star_dir=$(printf '%.0s.' ./.*/)
# Print pattern matches count excluding directories matches
printf 'Files count: %d\n' $((
${#star} - ${#star_dir} +
${#dot_star} - ${#dot_star_dir}
))
다음은 스크립트에서 사용할 수 있는 일반적인 Bash 함수입니다.
# @see https://stackoverflow.com/a/11307382/430062
function countFiles {
shopt -s nullglob
logfiles=($1)
echo ${#logfiles[@]}
}
FILES_COUNT=$(countFiles "$file-*")
ls -1 log* | wc -l
즉, 파일을 한 줄에 하나씩 나열한 다음 카운트 라인으로 전환하는 매개 변수를 사용하여 워드 카운트 명령으로 연결합니다.
제가 항상 하는 일은 다음과 같습니다.
lslog* | awk 'END{print NR}'
모든 항목을 카운트하려면 단어 카운트 라인에 파이프만 연결합니다.
ls | wc -l
패턴으로 카운트하려면 먼저 파이프에서 grep로:
ls | grep log | wc -l
언급URL : https://stackoverflow.com/questions/11307257/is-there-a-bash-command-which-counts-files
'programing' 카테고리의 다른 글
| 32비트 전용 Microsoft Common Controls(ListView)를 대체할 방법을 찾고 있습니다. (0) | 2023.05.04 |
|---|---|
| 여러 비동기 작업을 실행하고 모든 작업이 완료될 때까지 대기 (0) | 2023.05.04 |
| 응답을 피하는 방법.종료() Excel 파일 다운로드 중 "스레드가 중단되었습니다." 예외 (0) | 2023.04.29 |
| Swift에서 유형이 다른 Superclass 속성을 재정의하는 중 (0) | 2023.04.29 |
| ASP에서 최대 업로드 파일 크기를 늘리는 방법.NET? (0) | 2023.04.29 |