다음과 같은 방법으로 특정 숫자 사이의 파일 수를 계산합니다.
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
필터링합니다 . 내장되어 있기 때문에 문제 없습니다 .start
stop
printf
Argument list too long
bash
printf '%s\0' /home/me/*/file_*.txt |
grep -cEzf <(seq "$start" "$stop" | sed 's/.*/_&\.txt$/')
grep
여기서는 널 바이트를 처리할 수 있는 GNU 버전이 있다고 가정합니다. 이는 경로를 안전하게 처리하는 데 중요합니다. 널 바이트는 경로의 일부가 될 수 없는 유일한 문자이므로 이를 사용하여 경로를 구분할 수 있습니다.
GNU 버전이 없다면 개행 문자가 포함된 경로가 없다는 가정 하에 경로를 개행 문자로 구분하는 것을 생성할 수 있습니다. 플래그 \0
로 교체 \n
하고 제거하십시오 .-z
다른 것으로 변경하는 경우 명령을 …_*.txt
업데이트해야 할 수도 있습니다 .sed
답변3
eval
다른 선택의 여지가 없다면 사용하지 마십시오. 잠재적으로 위험한지 여부는$start
및 변수의 내용 에 따라 다릅니다$stop
. 불필요한 곳에 사용하는 습관을 들이는 것은 좋지 않습니다.ls
터미널에서 보는 것 이외의 용도로 출력을 사용하지 마십시오. 가장 간단한 방법으로 구문 분석을 시도하더라도ls
여러 가지 방법으로 실패할 수 있습니다. 사용아무것NUL로 구분된 파일 이름 목록을 생성할 수 있습니다.find -print0
일반적으로 좋은 선택입니다.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=3
and 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"