여러 명령으로 -exec 찾기


429

성공하지 않고 여러 명령으로 find -exec를 사용하려고합니다. 다음과 같은 명령이 가능한지 아는 사람이 있습니까?

find *.txt -exec echo "$(tail -1 '{}'),$(ls '{}')" \;

기본적으로 현재 디렉토리에있는 각 txt 파일의 마지막 줄을 인쇄하고 줄 끝에서 쉼표 뒤에 파일 이름을 인쇄하려고합니다.



1
명령의 가능성을 확인하는 한 시스템에서 시도하지 않았습니까?
스리랑

1
로부터 find매뉴얼 페이지 : There are unavoidable security problems surrounding use of the -exec option; you should use the -execdir option instead.unixhelp.ed.ac.uk/CGI/man-cgi?find
JVE999


@ JVE999 링크가 끊어짐, ss64.com/bash/find.html의
Keith M

답변:


658

find-exec명령에 여러 부분을 허용 합니다. 예를 들면 다음과 같습니다.

find . -name "*.txt" -exec echo {} \; -exec grep banana {} \;

이 경우 두 번째 명령은 @Caleb에서 언급 한 것처럼 첫 번째 명령이 성공적으로 반환 된 경우에만 실행됩니다. 성공 또는 실패에 관계없이 두 명령을 모두 실행하려면 다음 구성을 사용할 수 있습니다.

find . -name "*.txt" \( -exec echo {} \; -o -exec true \; \) -exec grep banana {} \;

두 번 grep하는 방법? 실패합니다 : find ./* -exec grep -v 'COLD,'{} \; -exec egrep -i "my_string"{} \;
rajeev

51
@rajeev 두 번째 exec는 첫 번째 리턴 코드가 성공한 경우에만 실행되며 그렇지 않으면 생략됩니다. 이것은 아마도이 대답에서 주목해야합니다.
Caleb

1
이것이 답이 될 것입니다
pylover

1
-necho에 의해 생성 된 줄 바꿈을 억제하기 위해 다른 답변 중 일부 에서 사용하는 것에 주목 하십시오. 두 번째 명령이 한 줄의 출력만을 생성하고 더 읽기 쉽기를 원할 때 편리합니다.
William Turrell

훌륭한 솔루션. 매력처럼 작동합니다.
Philippe Delteil


52

다음 중 하나 :

find *.txt -exec awk 'END {print $0 "," FILENAME}' {} \;

find *.txt -exec sh -c 'echo "$(tail -n 1 "$1"),$1"' _ {} \;

find *.txt -exec sh -c 'echo "$(sed -n "\$p" "$1"),$1"' _ {} \;

12
{} 이전의 밑줄은 무엇입니까?
qed

2
@qed :의 자리를 차지하는 버림 거리 값입니다 $0. "_"대신 "foobar"를 사용하여이를 시도하십시오 find /usr/bin -name find -exec sh -c 'echo "[$0] [$1]"' foobar {} \;.-출력 : "[foobar] [/ usr / bin / find]".
추후 공지가있을 때까지 일시 중지되었습니다.

1
@XuWang : 그렇습니다. 아시다시피 $0일반적으로 프로그램 이름 ( ARGV[0])입니다.
추후 공지가있을 때까지 일시 중지되었습니다.

3
이 방법에서 전달 된 스크립트는 sh -c큰 따옴표가 아닌 작은 따옴표로 묶어야합니다. 그렇지 않으면 $1잘못된 범위에 있습니다.
Nick

1
@Nick 인용 부호와는 아무런 관련이 없습니다 . '$1'변수 ( "\$1") 를 이탈하는 한 큰 따옴표로 쓸 수 있습니다 . 다른 문자도 이스케이프 할 수 있습니다 ( "\"").
Camilo Martin

22

다른 방법은 다음과 같습니다.

multiple_cmd() { 
    tail -n1 $1; 
    ls $1 
}; 
export -f multiple_cmd; 
find *.txt -exec bash -c 'multiple_cmd "$0"' {} \;

한 줄에

multiple_cmd() { tail -1 $1; ls $1 }; export -f multiple_cmd; find *.txt -exec bash -c 'multiple_cmd "$0"' {} \;
  • " multiple_cmd()"-함수입니다
  • " export -f multiple_cmd"-다른 서브 쉘이 볼 수 있도록 내보내기
  • " find *.txt -exec bash -c 'multiple_cmd "$0"' {} \;"-예제에서 함수를 실행할 것임을 찾으십시오.

이런 식으로 multiple_cmd는 필요한만큼 길고 복잡 할 수 있습니다.

도움이 되었기를 바랍니다.


완벽, 내가 필요한 것!
Anentropic

OSX에서 작동하지 않습니다
Thomas

@ Thomas하지만 osx에서 테스트 한이 라이너를 사용해보십시오. 나는 거기에 일부 파일 / 디렉토리가있는 'aaa'라는 디렉토리를 만들고 CD를 만들었습니다. 그런 다음, ~/aaa$ acmd() { echo x \"$1\" x; }; export -f acmd; find . -exec bash -c 'acmd {}' \;
barlop

@barlop, 나는 그 시도를 줄 것이다; 감사!
토마스

14

더 쉬운 방법이 있습니다 :

find ... | while read -r file; do
    echo "look at my $file, my $file is amazing";
done

또는

while read -r file; do
    echo "look at my $file, my $file is amazing";
done <<< "$(find ...)"

1
파일 이름은 개행 문자를 가질 수 있습니다. 이것이 find가 -print0 인수를 갖고 xargs가 -0 인수를 갖는 이유입니다.
abasterfield

@abasterfield 난 항상 야생 롤 사람들을 찾기 위해 결코 희망하지 않습니다
카밀로 마틴에게

1
내가하고 싶은 것은 "find ... -exec zcat {} | wc -l \;" 작동하지 않았습니다. 그러나 찾기 ... | -r 파일을 읽는 동안; echo "$ file : zcat $file | wc -l"; 다 작동합니다, 감사합니다!
Greg Dougherty

위의 의견에서 "zcat $ file | wc -l"주위에 "back ticks"가 있습니다. 불행히도 SO는 그것들을 포맷으로 바꿉니다. 그래서 올바른 코드가 보이는 실제 답변으로 추가했습니다
Greg Dougherty

1
@GregDougherty 백틱 `을 피하기 위해 백틱 을 피할 수 있습니다 \​`(여전히 $()대신 사용해야 하는 또 다른 이유입니다 ).
Camilo Martin

8

find 로이 작업을 수행 할 수 있는지 모르겠지만 대체 솔루션은 쉘 스크립트를 만들고 find로 실행하는 것입니다.

lastline.sh :

echo $(tail -1 $1),$1

스크립트를 실행 가능하게 만들기

chmod +x lastline.sh

사용 find:

find . -name "*.txt" -exec ./lastline.sh {} \;

7
백틱은 더 이상 사용되지 않으므로 $ (...)의 사용을 권장합니다. $ (...)는 더 읽기 쉽고, 글꼴 독립적이며, 중첩하기 쉽습니다. 감사합니다.
사용자가 알 수 없음

4

Denis의 첫 번째 답변은 문제를 해결하는 답변입니다. 그러나 실제로는 제목 제안과 같이 하나의 exec에서만 여러 명령으로 더 이상 찾을 수 없습니다. 몇 가지 명령으로 하나의 exec에 응답하려면 해결할 다른 것을 찾아야합니다. 예를 들면 다음과 같습니다.

여러 개의 {} 참조를 사용하여 1 개의 exec 명령을 사용하여 지난 7 일 동안 수정 된 .log 파일의 마지막 10000 행 유지

1) 어떤 파일에서 명령이 수행되는지 확인하십시오.

find / -name "*.log" -a -type f -a -mtime -7 -exec sh -c "echo tail -10000 {} \> fictmp; echo cat fictmp \> {} " \;

2) 수행 : (더 이상 "\>"이 아니라 ">"만 필요합니다.)

find / -name "*.log" -a -type f -a -mtime -7 -exec sh -c "tail -10000 {} > fictmp; cat fictmp > {} ; rm fictmp" \;


그러나 파일 이름 중 하나에 공백이 있으면 중단됩니다.
Camilo Martin

4

Camilo Martin 덕분에 관련 질문에 대답 할 수있었습니다.

내가하고 싶은 것은

find ... -exec zcat {} | wc -l \;

작동하지 않았습니다. 하나,

find ... | while read -r file; do echo "$file: `zcat $file | wc -l`"; done

작동하므로 감사합니다!


2

@ Tinker의 답변을 확장,

필자의 경우 파일 이름과 찾은 텍스트를 특정 텍스트가 포함 된 파일로 인쇄 command | command | command하려면 내부 를 만들어야했습니다 -exec.

나는 그것을 할 수 있었다 :

find . -name config -type f \( -exec  grep "bitbucket" {} \; -a -exec echo {} \;  \) 

결과는 다음과 같습니다.

    url = git@bitbucket.org:a/a.git
./a/.git/config
    url = git@bitbucket.org:b/b.git
./b/.git/config
    url = git@bitbucket.org:c/c.git
./c/.git/config

1
하나의 매개 변수 /dev/null를 사용하여 grep명령에 두 번째 인수로 전달하여 파일 이름과 grep'd 내용을 한 줄에 인쇄 할 수도 있습니다 -exec.find . -name config -type f -exec grep "bitbucket" {} /dev/null \;
Bill Feth

1

xargs를 사용해야합니다 :)

find *.txt -type f -exec tail -1 {} \; | xargs -ICONSTANT echo $(pwd),CONSTANT

다른 하나 (OSX 작업)

find *.txt -type f -exec echo ,$(PWD) {} + -exec tail -1 {} + | tr ' ' '/'

3
이것은 find일치하는 파일 수가 명령 행에 비해 너무 큰 상황 의 주요 사용 사례를 간과합니다 . -exec이 한계를 극복하는 방법입니다. 유틸리티를 파이프 아웃하면 그 이점이 없습니다.
Chris Johnson

xargs -n호출 당 일치 수를 선택하기 위해 존재합니다. 매 경기마다 xargs -n 1 foocmd실행 foocmd {}됩니다.
AndrewF

0

find+xargs대답.

아래 예는 모든 .html파일을 찾고 .BAK확장자가 추가 된 사본을 만듭니다 (예 : 1.html> 1.html.BAK).

자리 표시자가 여러 개인 단일 명령

find . -iname "*.html" -print0 | xargs -0 -I {} cp -- "{}" "{}.BAK"

자리 표시자가 여러 개인 여러 명령

find . -iname "*.html" -print0 | xargs -0 -I {} echo "cp -- {} {}.BAK ; echo {} >> /tmp/log.txt" | sh

# if you need to do anything bash-specific then pipe to bash instead of sh

이 명령 것 같은 하이픈으로 시작하거나 공백을 포함 할 파일과도 작업 -my file.html매개 변수 덕분에 인용하고, --이후 cp에 어떤 신호 cp파라미터의 끝과 실제 파일 이름의 시작입니다.

-print0 널 바이트 종결 자로 결과를 파이프합니다.


위한 xargs를-I {} 파라미터 정의 {}지정자로서 원하는 자리 표시자를 사용할 수 있습니다. -0입력 항목이 널로 구분됨을 나타냅니다.

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