ack 패턴과 일치하는 파일에서만 검색

ack 패턴과 일치하는 파일에서만 검색

확인 검색은 특정 "glob" 패턴과 일치하는 파일에 의해서만 수행될 수 있습니다(예: "bar*.c"라는 이름의 모든 파일에서 foo 검색). 주문하다

ack foo "bar*.c"

현재 디렉터리에만 적용됩니다.

참고: find -exec를 사용하면 가능하다는 것을 알고 있습니다.

find . -name "bar*.c" -type f -exec ack foo {} + 

하지만 find는 버전 제어 디렉터리를 건너뛰지 않기 때문에 작고 간단한 ack 명령을 원합니다.

답변1

카탈로그 검색

매뉴얼 페이지에 표시된 개요에 따르면 예라고 말하고 싶습니다. 디렉터리를 처리할 수 있지만 스위치를 보면 패턴을 기반으로 파일을 찾을 수는 없습니다. 그러기 위해서는 군대에 입대해야 합니다 find. 명령에는 에서 다운로드할 수 있는 ack옵션이 포함되어 있습니다 .--files-from=FILEfind

요약

       ack [options] PATTERN [FILE...]
       ack -f [options] [DIRECTORY...]

용법

   --files-from=FILE
       The list of files to be searched is specified in FILE.  The list of
       files are separated by newlines.  If FILE is "-", the list is
       loaded from standard input.

--ignore-file=원하는 것을 제공할 수 있는 옵션이 있지만 실제로 사용하기에는 약간 고통스러운 것 같습니다.

   --ignore-file=FILTERTYPE:FILTERARGS
       Ignore files matching FILTERTYPE:FILTERARGS.  The filters are
       specified identically to file type filters as seen in "Defining
       your own types".

특정 유형의 파일 검색

내가 생각할 수 있는 유일한 다른 방법은 ack스위치를 사용하는 것입니다 --type.

   --type=[no]TYPE
       Specify the types of files to include or exclude from a search.
       TYPE is a filetype, like perl or xml.  --type=perl can also be
       specified as --perl, and --type=noperl can be done as --noperl.

       If a file is of both type "foo" and "bar", specifying --foo and
       --nobar will exclude the file, because an exclusion takes
       precedence over an inclusion.

사용 가능한 유형을 보려면 다음을 수행하세요.

$ ack --help-types | grep -E "perl|cpp"

체재. 예를 들어 --type=perl과 --perl이 모두 유효합니다. --[아니요]cpp .cpp .cc .cxx .m .hpp .hh .h .hxx --[아니요]objcpp .mm .h --[아니요]perl .pl .pm .pod .t .psgi; 라인은 /^#!.*\bperl/ --[no]perltest .t와 일치합니다.

파일 이름(*.pm, *.pl, *.t 및 *.pod) 및 shebang 줄을 기반으로 모든 Perl 파일을 찾습니다.

$ ack -f --type perl 
examples/iwatch/iwatch/iwatch
examples/nytprof_perl/bad.pl

모든 C++ 파일 찾기:

$ ack -f --type=cpp
Shared/Scanner.h
Shared/Sorter.h
Shared/DicomHelper.cpp
Shared/DicomDeviationWriter.h

bar*.c에서 foo를 검색하세요.

그렇다면 원하는 것을 어떻게 달성할 수 있나요? find이 작업을 수행하려면 다음 방법을 사용해야 할 수도 있습니다 .

$ find adir -iname "bar*.c" | ack --files-from=- foo
adir/bar1.c
1:foo
2:foo

adir/dir1/bar1.c
1:foo
2:foo

또한 ack함수를 사용하여 파일 이름에서 지정된 패턴과 일치하는 파일을 검색한 다음( 사용 ) 또는 .. 을 사용하여 -g <pattern>이 목록을 두 번째 호출에 전달할 수도 있습니다.ack-x--files-from=-

사용 -x:

$ ack -g '\bbar.*.c$' | ack -x foo
bar1.c
1:foo
2:foo

dir1/bar1.c
1:foo
2:foo

사용 -files-from=-:

$ ack -g '\bbar.*.c$' | ack --files-from=- foo
bar1.c
1:foo
2:foo

dir1/bar1.c
1:foo
2:foo

두 경우 모두 다음 정규식을 사용하여 원하는 파일 이름과 일치시킵니다.

\bbar.*.c$

bar.*c이는 줄 끝 앵커로 명명되고 끝나는 파일과 일치합니다 . 또한 이름에 경계 문자가 사용되었는지 확인하고 싶습니다. 예를 들어 또는 같은 경계 문자가 포함된 파일의 경우 실패합니다..c$\b$bar.c%bar.c

답변2

파일 유형을 알고 있으면 쉽고 ack는 많은 파일 유형에 대해 알고 있습니다. 예를 들어 C 파일에서만 검색하려는 경우 다음을 수행할 수 있습니다.

ack --cc 'string'

그러나 알려진 확장 중 하나가 아닌 경우 고유한 유형을 정의해야 합니다. 이것은 작동합니다:

ack --type-set barc:match:/bar.+\.c/ --barc 'string'

--type-set 및 --barc가 필요합니다.

(메일링 리스트에도 도움을 준 Andy에게 감사드립니다.)

답변3

이것이 가장 빠르고 안전한 것 같습니다.

find . -name '*.c' | ack -x 'some string'

-엑스 STDIN에서 검색할 파일 목록을 읽습니다.

그러나 파일이 데이터베이스에 있으면 locate더 빠릅니다.

locate --basename '*.c' | ack -x 'some thing'

Locate는 구식 정규 표현식도 허용하는데 이는 약간 번거롭지만 파일을 찾고 있다면 c필요할 수도 있습니다. 예를 들어

locate --basename --regex '\.\(c\|cpp\|h\|hpp\|cc\)$' |
    ack -x 'some thing'

이는 간단히 다음과 같이 해석됩니다. "c, cpp, h, hpp 또는 cc로 끝나는 모든 파일 이름을 검색합니다."

@nyxee의 아주 좋은 질문에 대해 내가 볼 수 있는 유일한 대답은 다른 파이프를 추가하는 것입니다.

locate --basename --regex '\.\(c\|cpp\|h\|hpp\|cc\)$' |
    grep -v '/\.'                                     |
    ack -x 'some thing'

이렇게 하면 다음으로 시작하는 디렉터리나 하위 디렉터리를 건너뜁니다..

답변4

@chim님 답변이 제일 좋은데 댓글로 쓴거라 정식 답변으로 다시 올립니다...

ack -g '\bbar.*.c$' | ack -x foo

정규식 경로를 사용할 수 있다는 사실이 마음에 듭니다 ...

관련 정보