Locate 명령을 통해 전달된 non-symlink 파일 수를 계산하려고 합니다. 나는 여러 가지 옵션을 시도했는데 이것이 가장 유망하다고 생각합니다.
locate -r "$PWD.*\.c$" | xargs -0 -I{} test -f {} && echo "regular file" | wc -l
문제는 그것이 작동하지 않는다는 것입니다.
총 30개의 파일이 있는데 그 중 1개는 심볼릭 링크 wc -l
이므로 29
.
나는 xargs
그것을 완전히 건너 뛰려고했습니다.
locate -r "$PWD.*\.c$" | test -f && echo "regular file" | wc -l
나는 노력했다아니요심볼릭 링크:
locate -r "$PWD.*\.c$" | test ! -h && echo "regular file" | wc -l
locate -r "$PWD.*\.c$" | test ! -L && echo "regular file" | wc -l
locate
출력을 파이프하고 일반 파일 수와 심볼릭 링크 수를 계산하는 가장 효율적인 방법은 무엇입니까?
댓글에 답장하기
어떤 사람들은 연출 을 좋아합니다 locate
. find
불가지론자였으면 좋겠지만 locate
가능하면 사용하고 싶습니다. 댓글이 게시되었으며 질문에 답변하고 싶습니다.
updatedb
첫 번째 실행에는 30초가 걸리지만 후속 실행에는 4초만 걸립니다. 5분마다 달리는 것은cron
하루에 한 번이라는 기본값에 대한 무모한 반응입니다. 하지만 노트북의 CPU 사용량은 10~20%에 불과하고 렉도 전혀 없습니다.- 캐시를 삭제한 후
find
파일 하나를 찾는데 1분 9초가 소요됩니다 . - 캐시를 삭제한 후
locate
동일한 파일을 찾는데 1초가 소요됩니다 .
다음은 시스템에 복제할 수 있는 몇 가지 벤치마크입니다.
$ sudo -i
# sync; echo 1 > /proc/sys/vm/drop_caches; sync; echo 2 > /proc/sys/vm/drop_caches; sync; echo 3 > /proc/sys/vm/drop_caches; exit
logout
$ time locate .hidden.c | wc -l
1
real 0m0.790s
user 0m0.758s
sys 0m0.028s
$ sudo -i
# sync; echo 1 > /proc/sys/vm/drop_caches; sync; echo 2 > /proc/sys/vm/drop_caches; sync; echo 3 > /proc/sys/vm/drop_caches; exit
logout
$ time find / iname '.hidden.c' 2>/dev/null | wc -l
1888926
real 1m9.044s
user 0m5.158s
sys 0m15.004s
$ sudo -i
# sync; echo 1 > /proc/sys/vm/drop_caches; sync; echo 2 > /proc/sys/vm/drop_caches; sync; echo 3 > /proc/sys/vm/drop_caches; exit
logout
$ time sudo updatedb
real 0m29.323s
user 0m1.267s
sys 0m4.784s
$ time sudo updatedb
real 0m3.592s
user 0m0.479s
sys 0m1.211s
find
의심할 여지 없이 그보다 더 강력 locate
하지만 locate
몇 배 더 빠르고 구문도 기억하기 더 쉽습니다.
실제로, 오늘 생성된 파일을 포함하거나 오늘 삭제된 파일을 제외하도록 데이터베이스를 업데이트하려면 명령 에 대한 sudo updatedb
인수를 한 번에 실행하거나 전달해야 한다는 것을 기억해야 합니다 . 하지만 반면에 매개변수를 전달하는 것을 기억해야 합니다 .-u
locate
find
2>/dev/null
첫째로 내 노트북이 제대로 작동하지 않고 둘째로 게으르기 때문에 5분마다 cron
실행하기 로 결정했습니다 .updatedb
답변1
이 명령은 닫힙니다.
locate -r "$PWD.*\.c$" | xargs -0 -I{} test -f {} && echo "regular file" | wc -l
질문:
- xargs와 함께 nul로 구분된 입력을 사용하지만
locate
nul로 구분된 출력은 제공하지 않습니다. - 단일 파이프라인이 아닌 전체 파이프라인에 대해 실행
&& echo
됩니다 .locate | xargs
test
노력하다:
locate -0r "$PWD.*\.c$" | xargs -0 -I{} sh -c 'test -f "$1" && echo "regular file"' _ {} | wc -l
locate
다음을 사용하여 Null로 구분된 출력을 활성화합니다.-0
test
and 와 결합됨 ( 각 호출이 여러 파일을 처리하도록echo
매개변수 루프로 개선될 수 있음 )sh -c
sh
에는 여전히 정규식 연산자가 있습니다 $PWD
.
답변2
그리고 zsh
:
set -o extendedglob # best in ~/.zshrc
c_regular_files=(
${(0)^"$(locate -0 "${${PWD%/}//(#m)[]\\*?]/\\$MATCH}/*.c")"}(N.)
)
echo there are at least $#c_regular_files regular files whose name ends in .c
- for 에서
[
, 및?
를 이스케이프해야 하며 와일드카드 연산자로 해석하지 않아야 합니다( 파일 이름에 common , 을 포함하여 더 많은 연산자가 있는 정규 표현식의 경우 더욱 나쁩니다).\
*
$PWD
locate
-r
.
$PWD
==는/
특별히 처리되어야 합니다.$PWD
대신 을 사용하면 이를${PWD%/}
실행locate -0 "//*.c"
하고 아무것도 반환하지 않습니다.-0
파일은 NUL로 구분됩니다(파일 경로에 줄바꿈이 허용되므로 줄바꿈은 효과가 없습니다)..
이다정기적인문서. 대조적으로[ -f
, 일반 파일에 대한 심볼릭 링크는 제외됩니다. Symlink가 아닌 모든.c
파일(디렉토리, fifo, 소켓 등과 같은 다른 유형의 파일 허용)을 원하는.
경우^@
.
그럼에도 불구하고 locate
반환된 목록은 locate
데이터베이스가 마지막으로 업데이트된 시간을 기반으로 하므로 현재 현실을 반영하지 않을 수 있습니다.
답변3
구문 분석 대신 locate
(깨지기 쉬우며 데이터베이스가 마지막으로 업데이트된 이후 변경된 항목 또는 사용할 수 없는 항목을 놓칠 수 있음)모두사용자), find
.
.c
다음 명령은 현재 디렉토리에서 모든 일반 파일(심볼릭 링크 아님)에 대한 파일을 찾습니다 .
find . -type f -name '*.c'
주어진 디렉토리 구조
.
|-- file-a.c
|-- file-b.c
|-- file-c.c
|-- file-d.c
|-- link-b.c -> file-b.c
`-- link-d.c -> file-d.c
이 반환됩니다
./file-a.c
./file-b.c
./file-c.c
./file-d.c
세어보세요:
find . -type f -name '*.c' | wc -l
또는 파일 이름에 개행 문자가 포함된 경우
find .//. -name '*.c' -type f | grep -c //
심볼릭 링크로 동일한 작업을 수행하려면 -type f
로 변경 -type l
.
답변4
GNU Parallel을 사용하면 다음과 같습니다:
locate -r "$PWD.*\.c$" | parallel 'test -f {} && echo "regular file"' | wc -l
보시다시피 원래 시도와 매우 가깝습니다.
적중 수가 100개 미만인 경우 GNU Parallel을 사용하여 실패한 작업 수를 최대 100개로 설정할 수 있습니다(확장되지 않음).
ls *txt | parallel \! test -f {}
echo $?
더 빨리 필요한 경우:
locate -r "$PWD.*\.c$" |
perl -ne 'chomp; -l $_ or $s+= -f $_; END{print "$s\n"}'
또는 조합:
locate -r "$PWD.*\.c$" |
parallel --block 10k --pipe -q perl -ne 'chomp; -l $_ or $s+= -f $_; END{print "$s\n"}' |
awk '{s+=$1} END {print s}'