파이프를 포함 시키려면 | 내 리눅스에서 찾기 -exec 명령?


220

작동하지 않습니다. 이것을 찾아서 할 수 있습니까? 아니면 xargs해야합니까?

find -name 'file_*' -follow -type f -exec zcat {} \| agrep -dEOE 'grep' \;

답변:


145

파이프 기호를 여러 프로세스를 실행하고 한 프로세스의 출력을 다른 프로세스의 입력으로 파이프하는 명령으로 파이프 기호를 해석하는 작업은 쉘 (/ bin / sh 또는 이와 동등한)의 책임입니다.

예를 들어 최상위 쉘을 사용하여 다음과 같이 배관을 수행하도록 선택할 수 있습니다.

find -name 'file_*' -follow -type f -exec zcat {} \; | agrep -dEOE 'grep'

효율성 측면에서이 결과는 한 번의 찾기 호출, zcat의 여러 호출 및 한 번의 agrep 호출 비용이 듭니다.

이로 인해 단일 agrep 프로세스 만 생성되고 zcat의 수많은 호출로 생성 된 모든 출력을 처리합니다.

어떤 이유로 든 agrep을 여러 번 호출하려면 다음을 수행하십시오.

find . -name 'file_*' -follow -type f \
    -printf "zcat %p | agrep -dEOE 'grep'\n" | sh

파이프를 사용하여 명령 목록을 구성한 다음 실제로 실행할 새 셸로 보냅니다. (마지막 "| sh"를 생략하면 이와 같은 명령 행을 디버그하거나 실행하는 좋은 방법입니다.)

효율성 측면에서이 결과는 찾기 한 번의 호출, sh 한 번의 호출, zcat의 수많은 호출 및 수많은 agrep 호출의 비용이 듭니다.

명령 호출 수 측면에서 가장 효율적인 솔루션은 Paul Tomblin의 제안입니다.

find . -name "file_*" -follow -type f -print0 | xargs -0 zcat | agrep -dEOE 'grep'

... 한 번의 찾기 호출, xargs의 호출, zcat의 호출 및 agrep의 호출이 필요합니다.


1
xargs의 또 다른 장점은 -P 스위치 (-P 0)를 사용하여 최신 멀티 코어 CPU로 속도를 높일 수 있다는 것입니다.
flolo

예, -P Swich는 일반적으로 실행 속도를 높이는 좋은 방법입니다. 불행하게도, 병렬 zcat 프로세스의 출력이 파이프 인터리브로 파이프되어 결과에 영향을 줄 위험이 있습니다. 이 효과는 다음을 사용하여 설명 할 수 있습니다. echo -e "1 \ n2"| xargs -P 0 -n 1 예 | uniq
Rolf W. Rasmussen

@Adam, 제안한 변경을했습니다.
Paul Tomblin

splendid xjobs 명령 (원래 Solaris에서)을 설치할 수 있습니다
sehe

4
간단하고 일반적인 대답은에 있습니다 stackoverflow.com/a/21825690/42973 : -exec sh -c "… | … " \;.
Eric O Lebigot

278

해결책은 쉽다 : sh를 통해 실행

... -exec sh -c "zcat {} | agrep -dEOE 'grep' " \;

17
OP가 달성하려고 한 것은 위의 제안으로 충족 될 수 있지만 실제로 묻는 질문에 대답하는 것입니다. 이 방법으로해야 할 이유가 있습니다. exec는 find로 반환 된 파일을 조작하는 것보다, 특히 테스트와 결합 할 때보 다 훨씬 강력합니다. 예를 들면 다음과 같습니다. find geda-gaf / -type d -exec bash -c 'DIR = {}; [[$ (find $ DIR -maxdepth 1 | xargs grep -i spice | wc -l) -ge 5]] && echo $ DIR '\; spice 단어를 포함하는 해당 디렉토리의 모든 파일 중에서 총 5 줄 이상을 포함하는 검색 경로의 모든 디렉토리를 반환합니다.
swarfrat

3
가장 좋은 답변입니다. 전체 출력을 grepping하는 것은 (다른 답변이 제안하는 것처럼) 각 파일을 grep하는 것과 다릅니다. 팁 : sh 대신 원하는 다른 쉘을 사용할 수 있습니다 (bash로 시도했지만 정상적으로 실행 중입니다).
pagliuca

1
-c옵션을 간과하지 마십시오 . 그렇지 않으면 수수께끼 No such file or directory오류 메시지가 나타납니다.
asmaier

다음은 exec'd 셸 내부의 파이프를 사용하여 find를 사용하는 훌륭한 ps 교체입니다. / usr / bin / find / proc -mindepth 1 -maxdepth 1 -type d -regex '. * / [0-9] +'- print -exec bash -c "cat {} / cmdline | tr '\\ 0' ''; echo"\;
parity3

1
정규식을 사용하여 sed로 파일을 찾고 이름을 바꾸는 예find -type f -name '*.mdds' -exec sh -c "echo {} | sed -e 's/_[0-9]\+//g' | xargs mv {}" \;
Rostfrei

16
find . -name "file_*" -follow -type f -print0 | xargs -0 zcat | agrep -dEOE 'grep'

효율성상의 이유로 -print 및 xargs를 피하기를 희망합니다. 어쩌면 그것은 내 문제 일 수 있습니다. -exec를 통해 파이프 명령을 찾을 수 없음
someguy

이름에 공백이있는 파일에서는 작동하지 않습니다. 수정하려면 -print를 -print0으로 바꾸고 xargs에 -0 옵션을 추가하십시오
Adam Rosenfield

2
@someguy-뭐? 효율성으로 인해 xargs를 피하십니까? zcat의 한 인스턴스를 호출하고 여러 파일 목록을 전달하는 것은 발견 된 각 파일에 대해 새 인스턴스를 실행하는 것보다 훨씬 효율적입니다.
Sherm Pendley

@Adam-제안한 사항을 변경했습니다. 내가 찾은 시간의 99 %가 소스 코드 디렉토리에 있으며 공백이 없으므로 print0을 귀찮게하지 않습니다. 반면에 내 문서 디렉토리는 print0을 기억합니다.
Paul Tomblin

10

찾은 while파일에서 여러 작업을 수행 할 수 있는 루프로 파이프 할 수도 있습니다 find. 그래서 여기 jarjar파일 의 큰 배포판이있는 폴더의 주어진 Java 클래스 파일에 대한 아카이브 를 찾는 것이 있습니다

find /usr/lib/eclipse/plugins -type f -name \*.jar | while read jar; do echo $jar; jar tf $jar | fgrep IObservableList ; done

요점은 while 루프에 세미콜론으로 구분 된 전달 된 파일 이름을 참조하는 여러 명령이 포함되어 있으며 이러한 명령에는 파이프가 포함될 수 있다는 것입니다. 따라서이 예제에서는 일치하는 파일 이름을 에코 한 다음 지정된 클래스 이름에 대해 아카이브 필터링에있는 항목을 나열합니다. 결과는 다음과 같습니다.

/usr/lib/eclipse/plugins/org.eclipse.core.contenttype.source_3.4.1.R35x_v20090826-0451.jar /usr/lib/eclipse/plugins/org.eclipse.core.databinding.observable_1.2.0.M20090902-0800 .jar org / eclipse / core / databinding / observable / list / IObservableList .class /usr/lib/eclipse/plugins/org.eclipse.search.source_3.5.1.r351_v20090708-0800.jar / usr / lib / eclipse / plugins / org.eclipse.jdt.apt.core.source_3.3.202.R35x_v20091130-2300.jar /usr/lib/eclipse/plugins/org.eclipse.cvs.source_1.0.400.v201002111343.jar / usr / lib / eclipse / plugins / org.eclipse.help.appserver_3.1.400.v20090429_1800.jar

내 bash 쉘 (xubuntu10.04 / xfce) fgrep에서 일치하는 문자열을 강조 표시하면 일치 하는 클래스 이름을 굵게 표시합니다. 이렇게하면 jar검색된 수백 개의 파일 목록을 검색하고 일치하는 항목을 쉽게 볼 수 있습니다.

Windows에서는 다음과 같은 작업을 수행 할 수 있습니다.

for /R %j in (*.jar) do @echo %j & @jar tf %j | findstr IObservableList

Windows에서 명령 구분 기호는 '&'not ';'입니다. 그리고 '@'은 위의 linux find 출력과 같이 깔끔한 출력을 제공하는 명령의 에코를 억제합니다. 하지만 findstr당신이 일치하는 클래스 이름을보고 조금 더 가까이 출력에서 볼 필요가 있도록 일치하는 문자열 굵게 표시되지 않습니다. Windows 'for'명령은 텍스트 파일을 반복하는 것과 같은 몇 가지 트릭을 알고 있습니다 ...

즐겨


2

문자열 셸 명령 (sh -c)을 실행하는 것이 가장 좋습니다. 예를 들면 다음과 같습니다.

find -name 'file_*' -follow -type f -exec bash -c "zcat \"{}\" | agrep -dEOE 'grep'" \;

0

간단한 대안을 찾고 있다면 루프를 사용하여 수행 할 수 있습니다.

for i in $(find -name 'file_*' -follow -type f);do zcat $i | agrep -dEOE 'grep');done

또는보다 일반적이고 이해하기 쉬운 형태 :

for i in $(YOUR_FIND_COMMAND);do YOUR_EXEC_COMMAND_AND_PIPES );done

YOUR_EXEC_COMMAND_AND_PIPES에서 {}를 $ i로 바꿉니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.