스크립트에 오류가 있습니다. find 명령이 공백 문자가 있는 폴더를 건너뛰는 중입니다.

스크립트에 오류가 있습니다. find 명령이 공백 문자가 있는 폴더를 건너뛰는 중입니다.

디렉터리(및 하위)의 파일 수를 계산하는 스크립트가 필요합니다. 나는 다음 스크립트를 가져와 필요에 맞게 변경했습니다.

공백 문자가 있는 폴더를 제외하고는 정상적으로 작동합니다. 어디에서나 따옴표가 누락되었다고 확신하지만 아직 알아낼 ​​수는 없습니다.

추가 정보

  • Linux 2.6.22.19-0.4-default(이 서버는 더 이상 생산적인 환경에 있지 않습니다.)
  • GNU 찾기 버전 4.2.31
  • 디렉토리 이름을 바꿀 수 없습니다.

예제 디렉토리 구조

.
..
01_infos
02_sent
03_inbox
04_public and private
197.
145.
329.
13.

스크립트

#!/bin/bash
# Write a script that will count the number of files in each of your subdirectories.
# -------------------------------------------------------------------------
# Copyright (c) 2001 nixCraft project <http://cyberciti.biz/fb/>
# This script is licensed under GNU GPL version 2.0 or above
# -------------------------------------------------------------------------
# This script is part of nixCraft shell script collection (NSSC)
# Visit http://bash.cyberciti.biz/ for more information.
# -------------------------------------------------------------------------

START=$HOME

# change your directory to command line if passed
# otherwise use home directory
[ $# -eq 1 ] && START=$1 || :

if [ ! -d $START ]
then
        echo "$START not a directory!"
        exit 1
fi

# use find command to get all subdirs name in DIRS variable
DIRS=$(find "$START" -type d)

# loop thought each dir to get the number of files in each of subdir
for d in $DIRS
do
        echo "$d directory has $(find "$d" -maxdepth 1 -regex '.*\.' -type f | wc -l) files" || :
done

산출

./01_infos directory has 1 files
./02_sent directory has 9 files
./03_inbox has 4 files
find: ./04_public: No such file or directory

답변1

일부 큰따옴표가 누락되었습니다($foo변수 대체 및 명령 대체 에는 항상 큰따옴표를 사용하세요.$(foo), 안전하게 종료할 수 있고 종료해야 하는 이유를 알지 않는 한). 그러나 그것이 문제의 전부는 아닙니다.

if [ ! -d $START ]

해야한다 if [ ! -d "$START" ].

DIRS=$(find "$START" -type d)

이 시점에서 DIRS시작 디렉터리와 해당 하위 디렉터리의 이름이 사이에 개행 문자를 포함하여 반복적으로 포함됩니다. 따라서 개행 문자가 포함된 디렉토리 이름이 있으면 손실된 것입니다. 어떤 개행 문자가 디렉토리 이름에서 왔는지 구분 기호인지 아는 것은 불가능합니다. 파일 이름에 개행 문자가 없다는 것을 알고 있다면 의 출력을 구문 분석할 수 있지만 find어떻게 알 수 있습니까?

그건 그렇고, $(…)이것은 변수 할당이고 할당의 대체는 암시적으로 보호되기 때문에 여기에 큰따옴표를 사용하지 않아도 괜찮습니다. 그러나 export DIRS=$(…)유사하게 보호되지는 않습니다. 쉘 스크립팅에 능숙하지 않고 스크립트를 유지 관리하는 모든 사람들이 그렇지 않다면 따옴표를 사용하는 것이 가장 좋습니다.

for d in $DIRS

이것이 당신이 잃는 곳입니다. 단어로 분할하고 싶기 $DIRS때문에 큰따옴표를 넣을 수 없지만 $DIRS모든 요소가 함께 연결되어 있고 공백 안의 파일 이름이 따옴표로 묶지 않으면 구분 기호가 되기 때문에 큰따옴표가 필요합니다.


일반적으로 를 사용할 때는 find옵션을 사용하여 처리 명령을 호출하도록 해야 합니다 -exec. 파일 이름을 엄격하게 제어하지 않는 한 출력을 구문 분석하지 마십시오 find. 모호합니다.

find "$START" -type d -exec sh -c '
    echo "$0 directory has $(find "$0" -maxdepth 1 -regex ".*\\." -type f -printf \\n | wc -l) files whose name ends with ."
' {} \;

포함된 find명령에서 의 출력을 구문 분석하는 경우 find파일 이름에 개행 문자가 포함되어 있으면 카운트가 해제된다는 점을 다시 한 번 참고하세요.

답변2

이것만은 어때요?

find . -type d -exec sh -c '/bin/echo -n "{}"; find "{}" -maxdepth 1 -regex ".*\." -type f | wc -l; ' \;

출력은 달콤하지는 않지만 스크립트가 필요하지 않으며 공백이 있는 디렉토리와 기타 영숫자가 아닌 문자에서 작동합니다.

답변3

고전적인 인용 실수가 있습니다. for 루프를 다음과 같이 수정하세요.

for d in "$DIRS"

find또는 출력을 직접 공급할 수도 있습니다 . 예:

find "$START" -type d | while read d
do # and so on...

여담이지만, 항상 반환 값이 0이므로 || :비트는 완전히 중복됩니다 .echo

관련 정보