bash는 와일드카드를 사용하여 경로의 파일 수를 계산하고 변수에 할당합니다.

bash는 와일드카드를 사용하여 경로의 파일 수를 계산하고 변수에 할당합니다.

내가 무엇을 놓치고 있나요?

디렉토리에 있는 파일 중 주어진 패턴과 일치하는 파일 수를 찾아 변수에 할당하고 싶습니다.

명령줄에 직접 입력하면 제대로 작동합니다.

ls /backups/system\ db\ files/temp/daily/backup_filename_202203*.tar.gz | wc -l

(참고로 이는 *백업이 생성된 날짜 입니다 01. 등)0203

하지만 일단 bash 스크립트에 추가하면 실패합니다.

지금까지 나는 다음을 가지고 있습니다 :

base_dir="/backups/system\ db\ files/temp" 
sub_dir="${base_dir}/daily"
filename_base="backup_filename_"

그런 다음 다음을 실행하려고 합니다.

counter=$(ls ${sub_dir}/${filename_base_}202203*.tar.gz | wc -l)

또는 따옴표로:

counter=$(ls "${sub_dir}/${filename_base_}202203*.tar.gz" | wc -l)

첫 번째는 공백을 기준으로 분할하려고 시도하기 때문에 실패합니다. 두 번째는 와일드카드 문자를 찾기 위해 확장되지 않습니다 *.

나는 그 중 일부를 인용해 보았습니다.

counter=$(ls "${sub_dir}/${filename_base_}"202203*.tar.gz | wc -l)

그러나 이번에도 와일드카드를 무시합니다.

계속 찾고 있지만 일치하는 파일의 총 수를 얻는 방법을 평생 찾을 수 없습니다.

답변1

문제는 귀하의 디렉토리가 호출되지 않는다는 것 입니다 /backups/system\ db\ files/temp. backups/system db files/temp문자열을 인용하면 백슬래시가 문자열의 일부가 됩니다. 문자열을 인용했으므로 공백을 이스케이프 처리할 필요가 없습니다. filename_base또한 변수의 철자가 여러 곳에서 잘못되었습니다(후행 밑줄 포함) .

또한 쉘 패턴과 일치하는 이름의 수를 사용 ls하고 계산할 필요도 없습니다 . wc파일 이름에는 개행 문자가 포함될 수 있으며 wc -l파일 이름이 아닌 개행 문자만 계산됩니다.

쉘 패턴에 일치하는 항목이 몇 개 있는지 확인하려면 패턴을 배열 또는 위치 인수 목록으로 확장한 다음 해당 배열 또는 목록의 길이를 확인하기만 하면 됩니다.

예제 패턴과 함께 배열 사용:

list=( "some/path to the/files"/*.txt )

count=${#list[@]}

위치 인수 목록을 사용하십시오.

set -- "some/path to the/files"/*.txt

count=$#

bash쉘 에서는 빈 디렉토리를 적절하게 처리하기 nullglob위해 쉘 옵션을 설정해야 합니다 shopt -s nullglob(패턴이 아무것도 일치하지 않으면 일반적으로 패턴이 확장되지 않습니다).

설정되지 않은 경우 nullglob다음 명령을 사용하여 일치하는 항목이 없는지 테스트할 수 있습니다.

list=( "some/path to the/files"/*.txt )
count=${#list[@]}

if [ ! -e "${list[0]}" ] && [ ! -h "${list[0]}" ]; then
    count=0
fi

또는 위치 매개변수를 사용하는 경우

set -- "some/path to the/files"/*.txt
count=$#

if [ ! -e "$1" ] && [ ! -h "$1" ]; then
    count=0
fi

부정되고 테스트가 다음과 같은 -e경우-h진짜결과 목록의 첫 번째 요소의 경우 첫 번째 요소는 기존 파일이나 끊어진 기호 링크가 아닙니다. 이는 패턴과 일치하는 항목이 없음을 의미합니다.

답변2

인용할 때 공백을 벗어나지 마십시오. 그렇지 않으면 백슬래시가 문자 그대로 사용됩니다.

base_dir="/backups/system\ db\ files/temp" 

~해야 한다

base_dir="/backups/system db files/temp"

그리고 당신은 _그것을 왜 갖고 있나요 ${filename_base_}?

마지막 명령에는아마도다른 모든 것이 정확하면 다음과 같이 작동합니다.

counter=$(ls "${sub_dir}/${filename_base}"202203*.tar.gz | wc -l)

어쨌든 당신은파싱하면 안 된다ls.

대신 다음을 사용하십시오 find.

find "${sub_dir}" -name "${filename_base}202203*.tar.gz" -printf '.' | wc -c

또는 배열:

shopt -s nullglob
files=("${sub_dir}/${filename_base}"202203*.tar.gz)
echo "${#files[@]}"

이 옵션이 필요합니다 . 그렇지 않으면 문자열이 문자 그대로 처리되므로 패턴과 일치하는 파일이 없게 nullglob됩니다 .1

관련 정보