파일 검색 도구

14143 단어

파일 검색 도구



특정 상황에서 파일 출력이 문제가 되는 깊은 babel 문제가 발생했습니다. 모듈은 AMD이고 확장하는 클래스를 포함했습니다React.Component. 나는 그 문제가 내가 작업하고 있던 코드베이스에 얼마나 만연해 있는지 알지 못했다.
find . -type f | wc -l
42247 파일이 있다고 말했습니다.

그래서 내가 필요한 것은 특정 용어 세트를 찾는 모든 파일을 grep하는 것이 었습니다.

['Component {', 'define(', 'class', 'React']


이것은 확실한 증거는 아니지만 내가 원하는 것을 거의 얻을 수 있습니다. 몇 분 동안 샅샅이 뒤져본 후, 매우 복잡한 펄 정규식이나 전체 bash 스크립트를 작성해야 한다고 생각했습니다. 나는 이 둘 중 하나에 능숙하지 않고 시간이 부족하기 때문에 대신 노드 스크립트를 함께 던지기로 결정했습니다. 그리고 나는 내가 얼마나 빨리 결과를 얻을 수 있는지에 매우 만족했습니다!

내가 한 일은 다음과 같습니다.

mkcd search-terms-tool


mkcd는 디렉토리를 만들고 즉시 디렉토리로 이동하는 별명입니다. mkcd () { mkdir "$1" && cd $_ }
yarn init
yarn add fast-glob


모든 파일 경로를 쉽게 찾으려면 fast-glob이 필요합니다. 선택적으로 명령줄에서 검색할 경로를 읽기 위해 yargs를 추가할 수 있습니다. 시간적 압박이 있어서 그냥 코드에 직접 넣었습니다.

touch index.js


원하는 편집기를 엽니다. 내 것은 vscode입니다. 위에서 말했듯이 먼저 디렉토리에 있는 모든 JS 파일을 가져와야 합니다.

const fg = require('fast-glob');

const SEARCH_DIR = '/path/to/code';
const paths = fg.sync(`${SEARCH_DIR}/**/*.js`);

console.log(paths);


그런 다음 자동으로 실행되도록 하려면 코드를 실행하거나 실행nodemon하십시오.

node index.js


엄청난 양의 파일 목록이 표시되어야 합니다! 이것은 기본적으로 실행 코드의 한 줄이었고 우리는 절반 정도 왔습니다. 이제 모든 검색어를 포함하는 항목으로 필터링하기만 하면 됩니다. 내가 생각할 수 있는 가장 쉬운 방법은 노드 빌드fs를 사용하여 각 파일의 내용을 읽은 다음 .filter 검색어를 보고 .every를 읽는 것입니다.

const fs = require('fs');
const fg = require('fast-glob');

const searchTerms = ['Component {', 'define(', 'class', 'React'];

const SEARCH_DIR = '/path/to/code';
const paths = fg.sync(`${SEARCH_DIR}/**/*.js`);

const validPaths = paths.filter(path => {
  const contents = fs.readFileSync(path);
  return searchTerms.every(term => {
    return contents.includes(term);
  });
});

console.log(validPaths);


그리고 그게 다야! 나는 이것을 얼마나 빨리 함께 던질 수 있는지에 대해 꽤 바닥을 쳤다. 그리고 시간이 조금 더 있었기 때문에 파일 읽기를 병렬로 실행하고 결과를 파일에 쓰는 두 가지 업그레이드를 수행하기로 결정했습니다.

충분히 간단합니다. 약속 목록을 작성하고 실행Promise.all하여 필터링된 결과를 얻으십시오.

const util = require('util');

const readFile = util.promisify(fs.readFile);

const readAndCheckFile = async (path) => {
  const contents = await readFile(path);
  return searchTerms.every(term => contents.includes(term));
}

const printResults = validPaths =>
  fs.writeFileSync('./results.txt', validPaths.join('\n'));

Promise.all(paths.filter(readAndCheckFile)).catch(console.log).then(printResults);


처음 실행했는데 마지막 줄에 .catch가 없었고 프로그램이 터졌습니다 😬
.catch를 추가한 후 "너무 많은 파일이 열려 있습니다"오류를 발견했습니다. 빠른 Google 검색 후 오류가 발생하면 기다리는 graceful-fs를 찾았습니다. 가져오기를 변경하기만 하면 작동했습니다! 다음은 내가 사용한 최종 프로그램입니다.

const fs = require('graceful-fs');
const fg = require('fast-glob');
const util = require('util');

// Convert fs.readFile into Promise version of same
const readFile = util.promisify(fs.readFile);

// path to find files in (no trailing slash)
const SEARCH_DIR = '/path/to/code';

// order these by what will filter the most to least
const searchTerms = ['Component {', 'define(', 'class', 'React'];

// find all the paths to files to look in
const paths = fg.sync(`${SEARCH_DIR}/**/*.js`);

const readAndCheckFile = async path => {
  const contents = await readFile(path);
  // check if all the terms are in the file contents
  return searchTerms.every(term => contents.includes(term));
};

const printResults = validPaths =>
  fs.writeFileSync('./results.txt', validPaths.join('\n'));

Promise.all(paths.filter(path => readAndCheckFile(path)))
  .catch(err => console.log(err))
  .then(printResults)
  .then(() => console.log('SUCCESS!'));


노드와 JS 생태계에 완전히 익숙하지 않은 사람에게는 악몽이 될 수 있으며 아마도 bash 정규식 경로를 알아냈을 것입니다. 그 경로를 아시는 분은 알려주세요! 하지만 여기서 교훈은 이미 알고 있고 사랑하는 도구를 사용하는 것을 두려워하지 말라는 것입니다. 이것은 내가 토끼 ​​구멍을 피하는 데 도움이 되었고 제 시간에 문제를 해결했습니다.

행복한 코딩!

좋은 웹페이지 즐겨찾기