디렉토리에 있는 모든 파일의 상대 경로를 얻으려고 합니다. 수십만 개의 파일을 실행할 수 있으므로 속도가 빨라야 합니다.
나는 시도 find .
했고 rg --files
(rg
존재하다ripgrep
) rg
약 6배 더 빠릅니다.
이 작업을 더 잘하거나 더 빠르게 수행할 수 있는 기본 방법이 있습니까?
답변1
이는 속임수이며 업데이트된 위치 데이터베이스가 있다고 가정합니다(예:위치), 그러나 디렉토리 내용의 캐시를 구문 분석하므로 가장 빠릅니다.
locate "$PWD/*" |awk -v len="${#PWD}" '{ print substr($0, len+2) }'
데이터베이스는 매일 업데이트 되므로 미리 실행 locate
해야 할 수도 있습니다. 전체 파일 시스템을 인덱싱하므로 분명히 시간이 걸릴 수 있지만(ripgrep만큼 빠르지는 않을 수 있음) 여러 번 수행해야 하는 경우 sudo updatedb
, 한 번 캐싱하면 여전히 괜찮을 것입니다.
이 awk
코드는 지정된 경로를 기준으로 조회수를 인쇄합니다. 다음과 같은 기능으로 만들 수 있습니다.
# Usage: indir [DIRECTORY]
# Show recursive contents of DIRECTORY (defaults to current directory)
indir() {
d="$(readlink -f "${1:-$PWD}")"
locate "$d/*" |awk -v len="${#d}" '{ print substr($0, len+2) }'
}
readlink -f
(GNU Coreutils에서)는 입력을 정규화하므로 indir .
or 를 실행할 수 indir ../foo
있으며 계속 작동합니다(출력은 DIRECTORY를 기준으로 하므로 ../foo/bar/baz
로 표시됩니다 bar/baz
).
이 답변에 대한 설명에서 언급했듯이 쿼리 경로 이름에 와일드카드 문자( ?
또는 또는 )가 있으면 *
문제가 발생합니다 . […]
백슬래시를 사용하여 이스케이프 처리하면 이 문제를 해결할 수 있습니다(단, 길이가 변경된다는 점에 유의하세요).
또는 libpcre 지원으로 컴파일된 경우 GNU grep을 사용하여 이 작업을 수행할 수 있습니다.
# Usage: indir [DIRECTORY]
# Show recursive contents of DIRECTORY (defaults to current directory)
indir() {
d="$(readlink -f "${1:-$PWD}")"
locate "$d/*" |grep -Po "^\Q$d/\E\K.+"
}
PCRE를 사용하여 grep을 실행하고 일치하는 항목만 인쇄합니다. 정규식은 좀 더 복잡합니다.정규 표현식 101 설명). 이는 줄의 시작 부분( ^
)에서만 일치하며, 이는 리터럴 문자열 일치( \Q…\E
및 사이의 정규식 해석을 허용하지 않음)가 되며 일치로 보고되어야 하는 항목의 시작을 나타냅니다. 결국 해당 경로 이후의 모든 항목과 일치하게 되며, 이는 grep이 보고하는 유일한 것입니다. 디렉토리 이름 자체와 일치하지 않는지 확인하기 위해 리터럴을 넣었습니다. 하지만 이는 또한 match와 같은 다른 경로와 일치하지 않도록 합니다.\Q
\E
\K
.+
/
\Q…\E
/path/to/dirt
/path/to/dir