wc -c가 스크립트의 루프에서 작동하지 않습니다.

wc -c가 스크립트의 루프에서 작동하지 않습니다.

그래서 저는 파일 크기가 주어진 인수보다 작은지 확인하고 true이면 echo "YES"라고 말하는 간단한 스크립트를 작성하고 있습니다.

#!bin/bash

Function ()
{
    cd $1
    lista=`ls`
    for item in $lista
    do
        if [ ! -d $item ]
        then
            size=`wc -c $item | awk '{ print $1 }'`
            if [ $size -lt $2 ]
            then
                echo "$item"
            fi
        else
            Function $item $2
        fi
        cd ..
    done
}

Function $1 $2

그리고 카니발:

bash test2.sh /home/161161 300

그러나 두 번째 루프를 실행한 후 해당 파일이 없거나 존재하지 않는다는 오류가 발생하므로 wc -c에 문제가 있습니다.

어떤 아이디어가 있나요?

답변1

문제는 cd ..디렉터리의 모든 파일이 완료되기 전에 코드가 완료된다는 것입니다. 일반적으로 말하면, 파일 이름을 얻기 위해 디렉토리로 이동할 필요가 없으며 cd루프에서 디렉토리로 앞뒤로 이동하는 것은 혼란스러울 수 있습니다. 루프 내부의 출력을 상대 경로 등을 사용하여 파일 이름으로 리디렉션하면 이상한 문제가 발생할 수도 있습니다. 이 스크립트에서는 알 수 없습니다어디(어느 디렉토리에서) 항상 현재 디렉토리를 보기 때문에 파일이 발견됩니다.

을 사용하지 않거나 cd사용하지 않음 으로써 이 문제를 해결하세요 ls. 이렇게 하면 스크립트에서 공백 및 기타 특이한 문자가 포함된 파일 이름을 사용할 수 있습니다.

#!/bin/sh

find_smaller () {
    dir=$1
    size=$2

    for pathname in "$dir"/*; do
        if [ -f "$pathname" ]; then
            # this is a regular file (or a symbolic link to one), test its size
            filesize=$( wc -c <"$pathname" )
            if [ "$filesize" -lt "$size" ]; then
                printf 'Found %s, size is %d\n' "$pathname" "$filesize"
            fi
        elif [ -d "$pathname" ]; then
            # this is a directory (or a symbolic link to one), recurse
            printf 'Entering %s\n' "$pathname"
            find_smaller "$pathname" "$size"
        fi
    done
}

find_smaller "$@"

위 코드에서는 $pathname우리가 보고 있는 현재 파일이나 디렉터리의 파일 이름뿐만 아니라 시작 디렉터리에 대한 상대 경로도 표시됩니다.

또한 모든 변수 확장에 대한 참조를 참고하세요. $pathname예를 들어, 파일 이름에 *또는 같은 문자가 포함되어 있으면 변수를 인용하지 않고 파일 이름 globbing을 호출합니다 ?.

또한보십시오:


bash쉘 옵션 을 사용하십시오 globstar. 이 옵션이 설정되면 **전역 패턴은 지정된 디렉터리 아래의 모든 경로 이름과 일치합니다. 이는 스크립트에서 디렉터리 구조를 명시적으로 탐색할 필요가 없음을 의미합니다.

#!/bin/bash

dir="$1"
size="$2"

shopt -s globstar

for pathname in "$dir"/**; do
    [ ! -f "$pathname" ] && continue

    filesize=$( wc -c <"$pathname" )

    if [ "$filesize" -lt "$size" ]; then
        printf 'Found %s, size is %d\n' "$pathname" "$filesize"
    fi
done

find다음 find명령을 사용하여 코드에서 수행하려는 작업을 수행 할 수 있습니다 .

find /home/161161 -type f -size -100c

스크립트로:

#!/bin/sh
dir=$1
size=$2
find "$dir" -type f -size -"$size"c

명시적 디렉토리 워커와 find변형 사이의 유일한 약간의 차이점 find은 (위와 같이 사용될 때) 심볼릭 링크가 무시되는 반면 위의 쉘 함수는 심볼릭 링크를 해결하여 디렉토리 루프가 무한히 탐색되거나 동일한 데이터가 계산된다는 것입니다. 너무 많이 이류.

를 사용하면 find파일 크기를 계산하기 위해 파일 내용을 읽을 수 없습니다. 대신 lstat()파일 시스템에서 파일 크기를 쿼리하기 위해 라이브러리가 호출됩니다. 이것은많은를 사용하는 것보다 몇 배 더 빠릅니다 wc -c!

전부는 아니지만 대부분의 Unices에서는 명령줄 유틸리티를 사용하여 stat파일 크기를 확인할 수도 있습니다. 사용 방법을 알아보려면 시스템의 유틸리티 설명서를 참조하세요(Linux와 BSD에서는 다르게 작동합니다).

관련 정보