모든 하위 디렉터리의 파일 수를 보고하는 방법은 무엇입니까?

모든 하위 디렉터리의 파일 수를 보고하는 방법은 무엇입니까?

모든 하위 디렉터리를 확인하고 포함된 파일 수를 보고해야 합니다(추가 재귀 없이).

directoryName1 numberOfFiles
directoryName2 numberOfFiles

답변1

이는 안전하고 휴대 가능한 방식으로 수행됩니다. 이상한 파일 이름으로 인해 혼동되지 않습니다.

for f in *; do [ -d ./"$f" ] && find ./"$f" -maxdepth 1 -exec echo \; | wc -l && echo $f; done

먼저 파일 번호를 인쇄한 다음 디렉터리 이름을 별도의 줄에 인쇄합니다. OP의 형식을 유지하려면 추가 형식을 지정해야 합니다.

for f in *; do [ -d ./"$f" ] && find ./"$f" -maxdepth 1 -exec echo \;|wc -l|tr '\n' ' ' && echo $f; done|awk '{print $2"\t"$1}'

관심 있는 특정 하위 디렉터리 집합이 있는 경우 *이를 해당 하위 디렉터리로 바꿀 수 있습니다.

왜 그렇게 안전합니까?(따라서 대본에 합당함)

파일 이름에는 . 이외의 문자가 포함될 수 있습니다 /. 셸이나 명령에서 특별히 처리되는 문자가 있습니다. 여기에는 공백, 줄 바꿈 및 대시가 포함됩니다.

for f in *구조를 사용하는 것은 포함된 내용에 관계없이 모든 파일 이름을 얻는 안전한 방법입니다.

파일 이름을 변수에 넣은 후에도 방금 제공한 옵션을 포함하면 .filename 이 오류 를 발생시키는 것과 같은 문제를 피해야 합니다 find $f. 이를 피하는 방법은 이름 앞에 사용하는 것입니다. 이렇게 하면 동일한 의미를 갖지만 더 이상 대시로 시작하지 않습니다.$f-testfind./

줄 바꿈과 공백도 문제입니다. $f파일 이름에 "hello, buddy"가 포함 되어 있으면 find ./$f, 그렇습니다 find ./hello, buddy. 존재하지 않으면 불평하고 절대 찾지 않습니다 . 이는 피하기 쉽습니다. 변수 주위에 따옴표를 사용하십시오.find./hello,buddy./hello, buddy

마지막으로, 파일 이름에는 줄 바꿈이 포함될 수 있으므로 파일 이름 목록에서 줄 바꿈을 계산하는 것은 효과가 없습니다. 줄 바꿈이 있는 각 파일 이름에 대한 추가 개수를 얻게 됩니다. 이를 방지하려면 파일 목록에서 줄 바꿈을 계산하지 말고 대신 개별 파일을 나타내는 줄 바꿈(또는 기타 문자)을 계산하세요. 이것이 바로 find명령에 simple -exec echo \;과 not이 있는 이유입니다 -exec echo {} \;. 통계 파일에 새 줄을 인쇄하고 싶습니다.

답변2

"재귀 없음"은 directoryName1하위 디렉터리가 있는 경우 하위 디렉터리의 파일 수를 계산하지 않는다는 의미입니까? 그렇다면 지정된 디렉터리에 있는 모든 일반 파일의 개수를 계산하는 방법은 다음과 같습니다.

count=0
for d in directoryName1 directoryName2; do
  for f in "$d"/* "$d"/.[!.]* "$d"/..?*; do
    if [ -f "$f" ]; then count=$((count+1)); fi
  done
done

-f테스트는 두 가지 기능을 수행합니다. 위의 glob 중 하나와 일치하는 항목이 일반 파일인지 테스트하고 항목이 일치하는지 테스트합니다(glob 중 하나가 아무것도 일치하지 않으면 패턴은 1로 유지됩니다). . 유형에 관계없이 특정 디렉토리의 모든 항목 수를 계산하려면 -f로 바꾸십시오 -e.

Ksh에는 패턴을 도트 파일과 일치시키고 패턴과 일치하는 파일이 없으면 빈 목록을 생성하는 방법이 있습니다. 따라서 ksh에서는 다음과 같은 일반 파일을 계산할 수 있습니다.

FIGNORE='.?(.)'
count=0
for x in ~(N)directoryName1/* ~(N)directoryName2/*; do
  if [ -f "$x" ]; then ((++count)); fi
done

또는 다음과 같은 모든 파일:

FIGNORE='.?(.)'
files=(~(N)directoryName1/* ~(N)directoryName2/*)
count=${#files}

Bash에는 이 프로세스를 단순화하는 다양한 방법이 있습니다. 일반 파일 수를 계산하려면 다음을 수행하세요.

shopt -s dotglob nullglob
count=0
for x in directoryName1/* directoryName2/*; do
  if [ -f "$x" ]; then ((++count)); fi
done

모든 파일 수를 계산합니다.

shopt -s dotglob nullglob
files=(directoryName1/* directoryName2/*)
count=${#files}

평소와 마찬가지로 zsh에서는 훨씬 더 간단합니다. 일반 파일 수를 계산하려면 다음을 수행하세요.

files=({directoryName1,directoryName2}/*(DN.))
count=$#files

모든 파일을 계산 (DN.)하도록 변경합니다 .(DN)

1 각 패턴은 자체적으로 일치합니다. 그렇지 않으면 결과가 잘못될 수 있습니다(예: 숫자로 시작하는 파일의 수를 세는 경우 이름이 파일인 경우가 있을 수 있으므로 그렇게 할 수는 없습니다 ).for x in [0-9]*; do if [ -f "$x" ]; then …[0-9]foo

답변3

표준 Linux 솔루션을 찾고 있다고 가정하면 이를 달성하는 비교적 간단한 방법은 다음과 같습니다 find.

find dir1/ dir2/ -maxdepth 1 -type f | wc -l

여기서 1 find로 설정된 두 개의 지정된 하위 디렉터리를 순회합니다 -maxdepth. 이는 추가 재귀를 방지하고 줄 바꿈 -type f( )으로 구분된 파일만 보고합니다. 그런 다음 결과를 파이프로 연결하여 wc해당 행의 수를 계산합니다.

답변4

find이는 , echo, ls및 를 사용하여 결과를 얻는 "무차별적인" 방법입니다 wc.xargsawk

find . -maxdepth 1 -type d -exec sh -c "echo '{}'; ls -1 '{}' | wc -l" \; | xargs -n 2 | awk '{print $1" "$2}'

관련 정보