1
+ import { TaskQueue } from "./11-web-spider-v4/TaskQueue.js" ;
2
+ import { readdir , readFile } from 'fs' ;
3
+
4
+ /**
5
+ * ### 주어진 디렉터리에서 주어진 키워드를 포함하는 모든 텍스트파일을 찾는 함수
6
+ * - 모든 검색 완료 후 매칭되는 파일 리스트를 콜백을 사용하여 리턴.
7
+ * - 매칭되는 파일이 없으면 빈 배열을 리턴.
8
+ * - 재귀적으로 검색하기.
9
+ * - 디렉터리 및 파일검색, 키워드 검색을 병렬적으로 수행하기.
10
+ * - 제어 가능한 병렬 작업의 수를 유지하기.
11
+ *
12
+ * ### 검색 로직은 listNestedFiles 를 기반으로 약간 수정/추가 해서 만들고 동시성 제어는 예제 TeskQueue를 이용.
13
+ *
14
+ * @param {string } dir 로컬 파일시스템의 디렉터리 경로
15
+ * @param {string } keyword 텍스트 파일 내에서 찾을 키워드
16
+ * @param {(err, files) => any } cb
17
+ */
18
+ function recursiveFind ( dir , keyword , cb ) {
19
+
20
+ const fileList = [ ] ;
21
+
22
+ const workQueue = new TaskQueue ( 500 ) ;
23
+ workQueue . on ( 'error' , cb ) ;
24
+ workQueue . on ( 'empty' , ( ) => cb ( null , fileList ) ) ;
25
+
26
+ const next = ( nextDir , nextCb ) => {
27
+ readdir ( nextDir , { withFileTypes : true } , ( err , files ) => {
28
+ if ( err ) {
29
+ return nextCb ( err ) ;
30
+ } ;
31
+
32
+ const findTxtFileIncludingKeyword = ( fileName , taskCb ) => {
33
+ readFile ( `${ nextDir } /${ fileName } ` , 'utf8' , ( err , fileContent ) => {
34
+ if ( err ) {
35
+ return taskCb ( err ) ;
36
+ } ;
37
+ if ( fileContent . includes ( keyword ) ) {
38
+ fileList . push ( `${ nextDir } /${ fileName } ` ) ;
39
+ } ;
40
+ taskCb ( ) ;
41
+ } ) ;
42
+ } ;
43
+
44
+ files
45
+ . map ( f => { // txt 파일 대상 검색
46
+ if ( f . isFile ( ) && f . name . endsWith ( '.txt' ) ) {
47
+ workQueue . pushTask ( findTxtFileIncludingKeyword . bind ( null , f . name ) ) ;
48
+ }
49
+ return f ;
50
+ } )
51
+ . filter ( f => f . isDirectory ( ) )
52
+ . map ( f => f . name )
53
+ . filter ( f => f . charAt ( 0 ) !== '.' ) // 숨김폴더 제외
54
+ . forEach ( f => {
55
+ workQueue . pushTask ( ( taskCb ) => {
56
+ next ( `${ nextDir } /${ f } ` , taskCb ) ;
57
+ } ) ;
58
+ } ) ;
59
+
60
+ nextCb ( ) ;
61
+ } ) ;
62
+ } ;
63
+
64
+ workQueue . pushTask ( ( taskCb ) => {
65
+ next ( dir , taskCb ) ;
66
+ } ) ;
67
+
68
+ }
69
+
70
+
71
+
72
+ // --------------------------------------------------------------------------------
73
+
74
+
75
+
76
+ recursiveFind ( '../../' , 'number' , ( err , files ) => {
77
+ if ( err ) {
78
+ return console . error ( err ) ;
79
+ } ;
80
+ console . log ( files ) ;
81
+ } ) ;
0 commit comments