Linux 명령 : 텍스트 파일 만 '찾기'방법은 무엇입니까?


100

Google에서 몇 번 검색 한 후 다음과 같은 결과를 얻었습니다.

find my_folder -type f -exec grep -l "needle text" {} \; -exec file {} \; | grep text

매우 불편하고 MIME 유형 정보와 같은 불필요한 텍스트를 출력합니다. 더 나은 솔루션이 있습니까? 검색해야하는 많은 텍스트 파일과 함께 동일한 폴더에 많은 이미지와 기타 바이너리 파일이 있습니다.

답변:


184

나는 이것이 오래된 스레드라는 것을 알고 있지만 그것을 우연히 발견하고 find바이너리가 아닌 파일 만 찾는 데 사용하는 매우 빠른 방법 인 내 방법을 공유 할 것이라고 생각했습니다 .

find . -type f -exec grep -Iq . {} \; -print

-I그렙에 대한 옵션은 즉시 바이너리 파일과 무시하도록 지시 .과 함께 옵션을 -q즉시 확인이 매우 빠르게 진행 있도록 텍스트 파일을 일치합니다. 공백이 염려되는 경우 -print를 a -print0로 변경할 수 있습니다 xargs -0(팁 @ lucas.werkmeister!).

또한 첫 번째 점은 findOS X와 ​​같은 특정 BSD 버전에만 필요 하지만 별칭이나 무언가에 넣으려는 경우 항상 거기에 두는 것만으로도 손상되지 않습니다.

편집 : @ruslan이 올바르게 지적했듯이은 암시 적이므로 -and생략 할 수 있습니다.


16
Mac OS X에서는 이것을 find . -type f -exec grep -Il "" {} \;.
Alec Jacobson 2014 년

3
1. 실제로 질문 2. 그것은 방법이 더 성능이 좋은입니다 오탐 (false positive) 3. 양보하지 않는 응답 있기 때문 peoro의 대답보다 낫다
user123444555621

3
find -type f -exec grep -Iq . {} \; -and -print파일을 보관하는 이점이있는 것을 사용할 수도 있습니다 find. 텍스트 파일에 대해서만 실행 -print되는 다른 -exec것으로 대체 할 수 있습니다. (당신이 할 수있는 경우 grep파일 이름을 인쇄, 당신은 그들에 줄 바꿈와 파일 이름을 구별 할 수 없습니다.)
루카스 Werkmeister

1
@ NathanS.Watson-Haigh 텍스트 파일과 즉시 일치해야하므로 안됩니다. 공유 할 수있는 특정 사용 사례가 있습니까?
crudcore 17:37에

2
find . -type f -exec grep -Il . {} +훨씬 빠릅니다. 단점은 다른 확장 할 수 없다는 것입니다 -execlucas.werkmeister 제안 @로
헤닝


10

왜 불편한가요? 자주 사용해야하고 매번 타자하고 싶지 않은 경우 bash 함수를 정의하면됩니다.

function findTextInAsciiFiles {
    # usage: findTextInAsciiFiles DIRECTORY NEEDLE_TEXT
    find "$1" -type f -exec grep -l "$2" {} \; -exec file {} \; | grep text
}

그것을 넣고 .bashrc실행하십시오.

findTextInAsciiFiles your_folder "needle text"

당신이 원할 때마다.


편집은 영업 이익의 편집을 반영하기 :

MIME 정보를 잘라내려면 MIME 정보를 필터링하는 파이프 라인에 추가 단계를 추가하면됩니다. 이것은 앞에 오는 것만 취함으로써 트릭을 수행해야합니다 :: cut -d':' -f1:

function findTextInAsciiFiles {
    # usage: findTextInAsciiFiles DIRECTORY NEEDLE_TEXT
    find "$1" -type f -exec grep -l "$2" {} \; -exec file {} \; | grep text | cut -d ':' -f1
}

"grep text"가 정확히 모든 텍스트 파일을 얻을 수있을만큼 정확한지 확실하지 않습니다. 즉, MIME 유형 설명 문자열에 '텍스트'가없는 텍스트 파일 유형이 있습니까?
datasn.io 2011 년

@ kavoir.com : 예. 에서 file수동 : "사용자는 디렉토리에서 읽을 수있는 모든 파일이 단어를 '텍스트'인쇄가 아는에 따라 달라집니다."
peoro

2
텍스트 파일을 필터링 한 다음 필터링하는 대신, 검색하기 전에 텍스트 파일을 검색하는 것이 좀 더 영리하지 않을까요?
사용자 알 수없는

/proc/meminfo, /proc/cpuinfo등 텍스트 파일, 그러나 file /proc/meminfo말한다 /proc/meminfo: empty. '텍스트'외에 '비어 있음'을 테스트해야하는지 궁금하지만 다른 유형도 '비어 있음'을보고 할 수 있는지 확실하지 않습니다.
Timo Kähkönen 2013 년

"왜 불편한가요?" - "불필요한 텍스트 출력". 이 대답은 그것을 해결하지 않습니다.
user123444555621

4
find . -type f -print0 | xargs -0 file | grep -P text | cut -d: -f1 | xargs grep -Pil "search"

이것은 안타깝게도 공간 절약이 아닙니다. 이것을 bash 스크립트에 넣으면 조금 더 쉬워집니다.

이것은 공간 안전입니다.

#!/bin/bash
#if [ ! "$1" ] ; then
    echo "Usage: $0 <search>";
    exit
fi

find . -type f -print0 \
  | xargs -0 file \
  | grep -P text \
  | cut -d: -f1 \
  | xargs -i% grep -Pil "$1" "%"

2
스크립트에 몇 가지 문제가 있습니다. 1. 바이너리 파일의 이름이 지정되면 어떻게 text.bin됩니까? 2. 파일 이름에 :?
thkala 2011 년

3

이를 수행하는 또 다른 방법 :

# find . |xargs file {} \; |grep "ASCII text"

빈 파일도 원하는 경우 :

#  find . |xargs file {} \; |egrep "ASCII text|empty"

2

이건 어때요:

$ grep -rl "needle text" my_folder | tr '\n' '\0' | xargs -r -0 file | grep -e ':[^:]*text[^:]*$' | grep -v -e 'executable'

파일 유형없이 파일 이름을 원하면 최종 sed필터를 추가하기 만하면 됩니다.

$ grep -rl "needle text" my_folder | tr '\n' '\0' | xargs -r -0 file | grep -e ':[^:]*text[^:]*$' | grep -v -e 'executable' | sed 's|:[^:]*$||'

-e 'type'마지막 grep명령에 더 많은 옵션을 추가하여 불필요한 파일 유형을 필터링 할 수 있습니다 .

편집하다:

xargs버전이 -d옵션을 지원하는 경우 위의 명령이 더 간단 해집니다.

$ grep -rl "needle text" my_folder | xargs -d '\n' -r file | grep -e ':[^:]*text[^:]*$' | grep -v -e 'executable' | sed 's|:[^:]*$||'

바보 나. 재귀 적 grep을 인식하지 못했습니다. 많은 응용 프로그램에서 약간 제한되지만 실제로는 매우 빠릅니다. 당신을 위해 +1.
Antti Rytsölä 2011 년

2

내가 한 방법은 다음과 같습니다 ...

1 . 파일이 일반 텍스트인지 테스트하는 작은 스크립트를 만듭니다.

#!/bin/bash
[[ "$(file -bi $1)" == *"file"* ]]

2. 이전과 같이 find 사용

find . -type f -exec istext {} \; -exec grep -nHi mystring {} \;

무슨 뜻 == *"text"* ]]인가요?
사용자 알 수없는

대신 일치 연산자`= ~ "text"]]`를 사용할 수 있습니다.
사용자 알 수없는

2

histumness의 대답에는 두 가지 문제가 있습니다.

  • 텍스트 파일 만 나열합니다. 실제로 요청한대로 검색하지 않습니다. 실제로 검색하려면

    find . -type f -exec grep -Iq . {} \; -and -print0 | xargs -0 grep "needle text"
    
  • 매우 느린 모든 파일에 대해 grep 프로세스를 생성합니다. 그렇다면 더 나은 해결책은

    find . -type f -print0 | xargs -0 grep -IZl . | xargs -0 grep "needle text"
    

    또는 간단히

    find . -type f -print0 | xargs -0 grep -I "needle text"
    

    위의 솔루션 (2.5GB 데이터 / 7700 파일)의 경우 4 초에 비해 0.2 초 밖에 걸리지 않습니다 . 즉, 20 배 더 빠릅니다 .

또한 아무도 ag, Silver Searcher 또는 ack-grep ¸를 대안으로 인용하지 않았습니다 . 이 중 하나를 사용할 수있는 경우 훨씬 더 나은 대안입니다.

ag -t "needle text"    # Much faster than ack
ack -t "needle text"   # or ack-grep

마지막 으로 오 탐지 (텍스트 파일로 사용되는 바이너리 파일)에 주의하십시오 . 이미 grep / ag / ack를 사용하여 오 탐지가 있었으므로 파일을 편집하기 전에 일치하는 파일을 먼저 나열하는 것이 좋습니다.


1

오래된 질문이지만이 정보가 여기에 대한 답변의 품질을 더할 것이라고 생각합니다.

실행 가능한 비트가 설정된 파일 무시할 때 다음 명령을 사용합니다.

find . ! -perm -111

재귀 적으로 다른 디렉토리에 들어 가지 않도록하려면 :

find . -maxdepth 1 ! -perm -111

파이프 가 많은 명령을 혼합 할 필요가 없으며 강력한 일반 찾기 명령 만 있으면 됩니다.

  • 면책 조항 : 파일이 바이너리 인지 여부를 확인하지 않기 때문에 OP가 요청한 것과 정확히 다릅니다 . 예를 들어 텍스트 자체이지만 실행 가능한 비트가 설정된 bash 스크립트 파일을 필터링합니다 .

즉, 이것이 누구에게나 유용하기를 바랍니다.


0

1) 검색 할 파일 (~ 30k)이 너무 많기 때문에 아래 명령을 사용하여 crontab을 통해 사용할 텍스트 파일 목록을 매일 생성합니다.

find /to/src/folder -type f -exec file {} \; | grep text | cut -d: -f1 > ~/.src_list &

2) .bashrc에 함수를 만듭니다.

findex() {
    cat ~/.src_list | xargs grep "$*" 2>/dev/null
}

그런 다음 아래 명령을 사용하여 검색을 수행 할 수 있습니다.

findex "needle text"

HTH :)


0

나는 xargs를 선호한다

find . -type f | xargs grep -I "needle text"

파일 이름이 이상한 경우 -0 옵션을 사용하여 검색합니다.

find . -type f -print0 | xargs -0 grep -I "needle text"

0
  • 모든 text / ascii 파일에서 / etc의 "eth0"텍스트를 검색하는 bash 예제

grep eth0 $ (find / etc / -type f -exec 파일 {} \; | egrep -i "text | ascii"| cut -d ':'-f1)


0

한 줄에 두 개 이상의 명령을 입력하는 방법을 배우려는 저와 같은 초보자를위한 확장 된 설명이 포함 된 단순화 된 버전이 있습니다.

단계적으로 문제를 작성하면 다음과 같습니다.

// For every file in this directory
// Check the filetype
// If it's an ASCII file, then print out the filename

이를 위해 세 가지 UNIX 명령 findfile,,를 사용할 수 있습니다 grep.

find 디렉토리의 모든 파일을 확인합니다.

file파일 유형을 제공합니다. 우리의 경우 'ASCII 텍스트'의 반환을 찾고 있습니다.

grep 출력에서 'ASCII'키워드를 찾습니다. file

그렇다면 어떻게 한 줄로 묶을 수 있습니까? 이를 수행하는 방법은 여러 가지가 있지만 의사 코드 순서대로 수행하는 것이 가장 합리적이라는 것을 알았습니다 (특히 저와 같은 초보자에게).

find ./ -exec file {} ";" | grep 'ASCII'

복잡해 보이지만 분해하면 나쁘지 않습니다.

find ./=이 디렉토리의 모든 파일을 살펴 봅니다. 이 find명령은 '표현식'과 일치하는 파일의 파일 이름 또는 경로 뒤에 오는 모든 파일의 파일 이름을 인쇄합니다.이 경우에는 현재 디렉터리 또는./

이해해야 할 가장 중요한 것은 첫 번째 비트 이후의 모든 것이 True 또는 False로 평가된다는 것입니다. True이면 파일 이름이 인쇄됩니다. 그렇지 않은 경우 명령이 계속 진행됩니다.

-exec=이 플래그는 다른 명령의 결과를 검색 표현식으로 사용할 수 있도록하는 find 명령 내의 옵션입니다. 함수 내에서 함수를 호출하는 것과 같습니다.

file {}= 내부에서 호출되는 명령 find. 이 file명령은 파일의 파일 유형을 알려주는 문자열을 반환합니다. 정기적으로 다음과 같이 표시 file mytextfile.txt됩니다.. 우리의 경우, 우리는 find명령 이보고있는 파일을 사용하기를 원 하므로 {}빈 변수 또는 매개 변수 역할을하기 위해 중괄호 를 넣습니다 . 즉, 시스템이 디렉토리의 모든 파일에 대해 문자열을 출력하도록 요청하는 것입니다.

";"= 이것은에 의해 요구되며 명령 find끝에있는 구두점 -exec입니다. 를 실행하여 필요한 경우 자세한 설명은 '찾기'매뉴얼을 참조하십시오 man find.

| grep 'ASCII'= |파이프입니다. 파이프는 왼쪽에있는 모든 출력을 가져 와서 오른쪽에있는 입력으로 사용합니다. find명령 의 출력 (단일 파일의 파일 유형 인 문자열)을 가져 와서 문자열이 포함되어 있는지 테스트합니다 'ASCII'. 그렇다면 true를 반환합니다.

이제 오른쪽에있는 표현식 find ./grep명령이 true를 반환 할 때 true를 반환합니다. 짜잔.


0

file힘과 결합 된 멋진 유틸리티를 사용하여 매직 바이트로 파일 유형을 찾는 데 관심이 있다면 다음 과 같이 find유용 할 수 있습니다.

$ # Let's make some test files
$ mkdir ASCII-finder
$ cd ASCII-finder
$ dd if=/dev/urandom of=binary.file bs=1M count=1
1+0 records in
1+0 records out
1048576 bytes (1.0 MB, 1.0 MiB) copied, 0.009023 s, 116 MB/s
$ file binary.file
binary.file: data
$ echo 123 > text.txt
$ # Let the magic begin
$ find -type f -print0 | \
    xargs -0 -I @@ bash -c 'file "$@" | grep ASCII &>/dev/null && echo "file is ASCII: $@"' -- @@

산출:

file is ASCII: ./text.txt

범례 : $명령을 입력하는 대화 형 쉘 프롬프트입니다.

&&다른 스크립트를 호출하거나 인라인으로 다른 작업을 수행하기 위해 부분을 수정할 수 있습니다 . 즉, 파일에 주어진 문자열이 포함되어 있으면 전체 파일을 분류하거나 그 안에있는 보조 문자열을 찾을 수 있습니다.

설명:

  • find 파일 인 항목
  • 만들기는 xargs하나 개 라이너로 라인으로 각 항목을 공급 bash 명령 / 스크립트
  • file매직 바이트로 파일 유형을 grep확인하고 ASCII가 존재하는지 확인한 후 &&다음 명령이 실행 된 후에 확인 합니다.
  • find결과를 null분리하여 인쇄 합니다. 공백과 메타 문자가있는 파일 이름을 이스케이프하는 것이 좋습니다.
  • xargs, -0옵션을 사용하여 null구분 하여 읽고 -I @@ 각 레코드를 가져와 bash 스크립트에 대한 위치 매개 변수 / 인수로 사용합니다.
  • --for bash는 그것이 bash 옵션으로 해석 될 수 있는 -like -c로 시작하는 경우에도 인수 인 뒤에 오는 모든 것을 보장합니다.

ASCII 이외의 유형을 찾으려면 다음 grep ASCII과 같이 다른 유형으로 바꾸십시오.grep "PDF document, version 1.4"


-1
find . -type f | xargs file | grep "ASCII text" | awk -F: '{print $1}'

find 명령을 사용하여 모든 파일을 나열하고 file 명령을 사용하여 파일이 텍스트 (tar, key 아님)인지 확인하고 마지막으로 awk 명령을 사용하여 결과를 필터링하고 인쇄합니다.


-4

이건 어때요

 find . -type f|xargs grep "needle text"

이를 위해 보이지 않는"needle text"
peoro

@Navi : 제공된 예제 OP는 다음을 포함하는 파일 만 찾습니다."needl text"
peoro

3
@Navi : 이제 더 이상 텍스트 파일을 찾지 않습니다. 바이너리 파일에 포함되어 "needle text"있으면 찾을 수 있습니다.
peoro

내가 왜 당신의 말을 듣고 있습니까?
Navi

1
@Navi : 또한 파일 형식을 확인하지 않는 한 줄은 ... 파일 이름에 공백으로 큰 문제가 있습니다
thkala
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.