내가 무엇을 놓치고 있나요?
디렉토리에 있는 파일 중 주어진 패턴과 일치하는 파일 수를 찾아 변수에 할당하고 싶습니다.
명령줄에 직접 입력하면 제대로 작동합니다.
ls /backups/system\ db\ files/temp/daily/backup_filename_202203*.tar.gz | wc -l
(참고로 이는 *
백업이 생성된 날짜 입니다 01
. 등)02
03
하지만 일단 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