약 5 백만 개의 파일 이있는 디렉토리가있었습니다 . ls
이 디렉토리 내에서 명령 을 실행하려고 할 때 시스템이 엄청난 양의 메모리를 소비했으며 언젠가는 중단되었습니다. ls
명령을 사용하지 않고 파일을 나열하는 효율적인 방법이 있습니까?
ls
전화입니까 아니면 옵션을 사용 했습니까?
약 5 백만 개의 파일 이있는 디렉토리가있었습니다 . ls
이 디렉토리 내에서 명령 을 실행하려고 할 때 시스템이 엄청난 양의 메모리를 소비했으며 언젠가는 중단되었습니다. ls
명령을 사용하지 않고 파일을 나열하는 효율적인 방법이 있습니까?
ls
전화입니까 아니면 옵션을 사용 했습니까?
답변:
다음을 사용하여 정렬하지 마십시오.
ls --sort=none # "do not sort; list entries in directory order"
또는 동등하게 :
ls -U
-1
깃발을 추가하면 도움이 될 수 있습니다.
-1
더 오래 걸리는 것 같습니다 .
-C
stdout이 터미널 인 -1
경우 파이프 인 경우)이 혼동됩니다. 실험하고 측정 할 때는 출력을보고 (명령이 예상 한대로 작동하는지 확인) 억제하는 것 (터미널 응용 프로그램 처리량의 혼란 요소를 피하기 위해) 사이를 전환합니다. 더 나은 그렇게 명시를 통해 출력 형식을 정의, 두 모드에서 동일한 방식으로 동작 명령을 사용 -1
, -C
, -l
, 등
ls
실제로 파일을 정렬하고 디렉토리에 백만 개가 넘는 파일을 나열하려고하면 파일을 나열하려고합니다. 이 링크 에서 언급했듯이 strace
또는 find
파일을 사용 하거나 나열 할 수 있습니다. 그러나 5 백만 개의 파일이 있기 때문에 이러한 옵션도 내 문제에 적합하지 않은 것으로 보입니다. 인터넷 검색의 일부 비트 후, 나는 우리가 사용하는 디렉토리를 게시하면 발견 getdents()
하기 때문에, 빠른 있어야하는데 ls
, find
및 Python
라이브러리를 사용 readdir()
느리지 만 사용하는 getdents()
아래.
우리는 사용하여 파일을 나열하는 C 코드를 찾을 수 있습니다 getdents()
에서 여기를 :
/*
* List directories using getdents() because ls, find and Python libraries
* use readdir() which is slower (but uses getdents() underneath.
*
* Compile with
* ]$ gcc getdents.c -o getdents
*/
#define _GNU_SOURCE
#include <dirent.h> /* Defines DT_* constants */
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#define handle_error(msg) \
do { perror(msg); exit(EXIT_FAILURE); } while (0)
struct linux_dirent {
long d_ino;
off_t d_off;
unsigned short d_reclen;
char d_name[];
};
#define BUF_SIZE 1024*1024*5
int
main(int argc, char *argv[])
{
int fd, nread;
char buf[BUF_SIZE];
struct linux_dirent *d;
int bpos;
char d_type;
fd = open(argc > 1 ? argv[1] : ".", O_RDONLY | O_DIRECTORY);
if (fd == -1)
handle_error("open");
for ( ; ; ) {
nread = syscall(SYS_getdents, fd, buf, BUF_SIZE);
if (nread == -1)
handle_error("getdents");
if (nread == 0)
break;
for (bpos = 0; bpos < nread;) {
d = (struct linux_dirent *) (buf + bpos);
d_type = *(buf + bpos + d->d_reclen - 1);
if( d->d_ino != 0 && d_type == DT_REG ) {
printf("%s\n", (char *)d->d_name );
}
bpos += d->d_reclen;
}
}
exit(EXIT_SUCCESS);
}
위의 C 프로그램을 파일을 나열해야하는 디렉토리에 복사하십시오. 그런 다음 아래 명령을 실행하십시오.
gcc getdents.c -o getdents
./getdents
타이밍 예 : 시스템 구성에 따라 getdents
보다 빠를 수 있습니다 ls -f
. 다음은 컴퓨팅 클러스터의 NFS 마운트를 통해 약 500k 파일을 포함하는 디렉토리를 나열하는 데 40 배 속도가 향상된 것을 보여주는 몇 가지 타이밍입니다. 각 명령은 즉시 연속해서 10 번 실행 된 getdents
다음에 ls -f
. 첫 번째 실행은 NFS 캐싱 페이지 결함으로 인해 다른 모든 것보다 상당히 느립니다. (제외 :이 마운트를 통해 d_type
많은 파일이 "알 수없는"유형으로 표시된다는 점에서 필드를 신뢰할 수 없습니다.)
command: getdents $bigdir
usr:0.08 sys:0.96 wall:280.79 CPU:0%
usr:0.06 sys:0.18 wall:0.25 CPU:97%
usr:0.05 sys:0.16 wall:0.21 CPU:99%
usr:0.04 sys:0.18 wall:0.23 CPU:98%
usr:0.05 sys:0.20 wall:0.26 CPU:99%
usr:0.04 sys:0.18 wall:0.22 CPU:99%
usr:0.04 sys:0.17 wall:0.22 CPU:99%
usr:0.04 sys:0.20 wall:0.25 CPU:99%
usr:0.06 sys:0.18 wall:0.25 CPU:98%
usr:0.06 sys:0.18 wall:0.25 CPU:98%
command: /bin/ls -f $bigdir
usr:0.53 sys:8.39 wall:8.97 CPU:99%
usr:0.53 sys:7.65 wall:8.20 CPU:99%
usr:0.44 sys:7.91 wall:8.36 CPU:99%
usr:0.50 sys:8.00 wall:8.51 CPU:100%
usr:0.41 sys:7.73 wall:8.15 CPU:99%
usr:0.47 sys:8.84 wall:9.32 CPU:99%
usr:0.57 sys:9.78 wall:10.36 CPU:99%
usr:0.53 sys:10.75 wall:11.29 CPU:99%
usr:0.46 sys:8.76 wall:9.25 CPU:99%
usr:0.50 sys:8.58 wall:9.13 CPU:99%
ls
있습니까?
getdents
놓 readdir
칩니다.
속도가 느린 가장 큰 이유는 파일 유형의 색상이므로 색상 옵션을 사용 \ls
하거나 /bin/ls
사용 하지 않도록 설정할 수 있습니다.
실제로 디렉토리에 너무 많은 파일이 있으면 find
대신 사용 하는 것이 좋습니다.
ls -U --color
처리하는 데 시간이 오래 걸립니다 stat
. 그래서 둘 다 맞습니다.
ls
기본적으로 별명으로 표시됩니다 .bashrc
.
/bin/ls -U
, 아주 오랜 시간을 기다리는 것과 비교하여 시간이
나는 그것이 echo *
ls보다 훨씬 빨리 작동 한다는 것을 알았습니다. YMMV.
*
. 따라서이 방법은 5 백만 개의 파일에 대해서는 여전히 매우 느립니다.
ls
하는 사용--color
또는-F
그와 같은 일을 의미lstat(2)
각 파일에 대해.