루프의 파일 수 계산

루프의 파일 수 계산

다음과 같은 방법으로 특정 숫자 사이의 파일 수를 계산합니다.

for i in $(eval echo {$start..$stop}); do
ls /home/me/*/file_$i.txt 2> /dev/null | wc -l
done

$(eval echo {$start..$stop})시퀀스 표현식은 일반 입력을 받아들일 수 없기 때문에 필요합니다.

그러나 루프를 반복할 때마다 해당 단일 파일이 존재하는지 여부를 계산하기 때문에 이는 내가 원하는 작업을 수행하지 않습니다. 대신, 모든 파일에 대해 반복하면서 $start와 $stop 사이에 있는 총 수를 계산하기를 원합니다. (저는 많은 수의 파일을 다루고 오버플로를 피하려고 노력하고 있다는 점을 명심하십시오.) 파일이 존재하는지 각 반복을 확인하는 대신 기존 파일의 총 수를 계산하도록 위 구성표를 어떻게 수정할 수 있습니까?

답변1

이 시도,

Count=0
for i in {$start..$stop}; do
   Counter="$(ls /home/me/*/file_$i.txt 2> /dev/null | wc -l)"
   Count=$((Count+Counter))
done
echo "$Count"

답변2

루프를 전혀 사용하지 마십시오. 대신 목록을 작성하세요.모두grep파일을 검색하고 또는 같은 명령을 사용하여 및 사이의 파일을 akw필터링합니다 . 내장되어 있기 때문에 문제 없습니다 .startstopprintfArgument list too longbash

printf '%s\0' /home/me/*/file_*.txt |
grep -cEzf <(seq "$start" "$stop" | sed 's/.*/_&\.txt$/')

grep여기서는 널 바이트를 처리할 수 있는 GNU 버전이 있다고 가정합니다. 이는 경로를 안전하게 처리하는 데 중요합니다. 널 바이트는 경로의 일부가 될 수 없는 유일한 문자이므로 이를 사용하여 경로를 구분할 수 있습니다.
GNU 버전이 없다면 개행 문자가 포함된 경로가 없다는 가정 하에 경로를 개행 문자로 구분하는 것을 생성할 수 있습니다. 플래그 \0로 교체 \n하고 제거하십시오 .-z

다른 것으로 변경하는 경우 명령을 …_*.txt업데이트해야 할 수도 있습니다 .sed

답변3

  1. eval다른 선택의 여지가 없다면 사용하지 마십시오. 잠재적으로 위험한지 여부는 $start및 변수의 내용 에 따라 다릅니다 $stop. 불필요한 곳에 사용하는 습관을 들이는 것은 좋지 않습니다.

  2. ls터미널에서 보는 것 이외의 용도로 출력을 사용하지 마십시오. 가장 간단한 방법으로 구문 분석을 시도하더라도 ls여러 가지 방법으로 실패할 수 있습니다. 사용아무것NUL로 구분된 파일 이름 목록을 생성할 수 있습니다. find -print0일반적으로 좋은 선택입니다.

  3. Bash 내장 {x..y}시퀀스 확장은 변수를 평가할 수 없지만 독립 실행형 seq프로그램은 변수를 인수로 사용할 수 있습니다. 또한 -s구분 기호를 지정하는 유용한 옵션도 있습니다 .

다음에는 NUL로 구분된 입력 레코드 옵션(예: GNU, FreeBSD 및 기타 대부분의 버전)을 grep지원하는 버전이 필요합니다.-z현대의버전 grep).

# build a regular expression matching the desired sequence
re="$(seq -s '|' "$start" "$stop")"

# use the RE with `find ... -print0` and `grep -E -z -c`
find /home/me/*/ -maxdepth 1 -type f -name 'file_*.txt' -print0 | 
  grep -Ezc "/file_($re)\.txt$"

예를 들어, start=3and stop=7이면 $re은 입니다 3|4|5|6|7. 그러면 명령 grep이 다음으로 확장됩니다.

grep -Ezc "/file_(3|4|5|6|7)\.txt$"

그런데 명령 -name 'file_*.txt'의 매개변수 find는 필요하지 않습니다. 삭제해도 파이프라인은 오류 없이 계속 실행됩니다. 그들이 하는 일은 처리해야 할 입력 데이터를 줄이는 것뿐입니다 grep. 기껏해야 아주 사소한 최적화입니다.

예를 들어

find /home/me/*/ -maxdepth 1 -type f -print0 | grep -Ezc "/file_($re)\.txt$"

답변4

올바르게 이해했다면 루프가 필요하지 않습니다.

범위가 12에서 76 사이라고 가정합니다.

ls -l | grep -e "file_1[2-9].txt" -e "file_[2-6][0-9].txt" -e "file_7[0-6].txt"

문서 12~19

"file_1[2-9].txt"

문서 20~69:

"file_[2-6][0-9].txt"

문서 70~76

"file_7[0-6].txt"

관련 정보