find 명령의 -exec에서 두 개의 bash 명령을 어떻게 사용합니까?


32

명령 -exec부분에 2 개의 명령을 사용할 수 find있습니까?

나는 다음과 같은 것을 시도했다.

find . -name "*" -exec  chgrp -v new_group {}  ; chmod -v 770 {}  \;

그리고 나는 얻는다 :

찾기 : -exec에 대한 인수 누락
chmod : {}에 액세스 할 수 없습니다 : 해당 파일 또는 디렉토리
가 없습니다. chmod : 액세스 할 수 없습니다. :: 해당 파일 또는 디렉토리가 없습니다.

답변:


44

에 관해서는 find명령, 당신은 또한 단지 더 추가 할 수 있습니다 -exec행에서 명령을 :

find . -name "*" -exec chgrp -v new_group '{}' \; -exec chmod -v 770 '{}' \;

이 명령은 결과적으로 사용하는 것과 같습니다.

chgrp -v new_group 파일 && chmod -v 770 파일

각 파일에.

모든 find등의 매개 변수 -name, -exec, -size등에는 실제로 테스트 : find전체 체인 지금까지로 평가 한만큼 하나씩 계속 실행됩니다 사실 . 따라서 각 연속 -exec명령은 이전 명령이 true를 반환 한 경우에만 실행 됩니다 (즉 , 명령의 종료 상태). 그러나 또한 논리 사업자 등 이해 또는 ( ) 및 하지를 ( ). 따라서 이전 결과에 관계없이 일련의 테스트 를 사용하려면 다음과 같은 것을 사용해야합니다.0find-o!-exec

find . -name "*" \( -exec chgrp -v new_group {} \; -o -exec chmod -v 770 {} \; \)

4
+1 : 그렇습니다. 가장 우아한 방법입니다. 당신이 설명 할 수 있다면, 왜 사용 '{}'(괄호 주위에 아포스트로피), 방문하십시오 : unix.stackexchange.com/q/8647/4485
사용자 알 수없는

1
@user 불행히도, 여전히 필요한지 모르겠습니다. 나는 지금 약간의 테스트를했는데 아무것도 바뀌지 않는 상황을 보지 못했습니다. 나는 그것이 "좋은 습관"일 것이라고 생각합니다.
rozcietrzewiacz

2
따옴표는 이름에 공백이있는 파일에 중요합니다.
naught101

17
find . -name "*" -exec sh -c 'chgrp -v new_group "$0" ; chmod -v 770 "$0"' {} \;

@Gilles : -c$ 0의 홀수 처리에 대한 경이로움은 내가 볼 때마다 이것이 잘못되었다고 생각하게 만듭니다.
derobert

명시 적 쉘 같은 나는 정의되는 ...
djangofan

이 답변 (및 Giles의 답변)은에 주어진 질문에 대한 더 나은 답변 인 것 같습니다 sh -c.

14

명령은 먼저 쉘에 의해 ;개행과 동등한 두 개의 명령으로 구문 분석됩니다 .

find . -name "*" -exec chgrp -v new_group {}
chmod -v 770 {} \;

쉘 명령을 실행하려면 다음을 사용하여 쉘을 명시 적으로 호출하십시오 bash -c(또는 sh -c쉘이 특별히 배쉬인지 신경 쓰지 않는 경우).

find . -name "*" -exec sh -c 'chgrp -v new_group "$0"; chmod -v 770 "$0"' {} \;

{}쉘에 대한 인수로 사용하는 것에 주목하십시오 . 그것은 0 번째 인수입니다 (일반적으로 쉘 또는 스크립트의 이름이지만 여기서는 중요하지 않습니다) "$0".

한 번에 여러 파일 이름을 셸에 전달하고 셸을 반복하여 만들면 더 빠릅니다. 여기서는 _스크립트 이름으로 전달 하고 다음 인수는 파일 이름이며 for x(바로 가기 for x in "$@")가 반복됩니다.

find . -name "*" -exec sh -c 'for x; do chgrp -v new_group "$x"; chmod -v 770 "$x"; done' _ {} +

bash 4 이후 또는 zsh에서는 여기에서 전혀 찾을 필요가 없습니다. bash에서 재귀 디렉토리 glob 서를 활성화 하려면을 실행 shopt -s globstar하십시오 . (zsh에서는 항상 활성화됩니다.) 그런 다음~/.bashrc**/

chgrp -v new_group -- **/*; chmod -v 770 -- **/*

또는 파일을 순서대로 반복하려면

for x in **/*; do
  chgrp -v new_group -- "$x"
  chmod -v 770 -- "$x"
done

find명령 과 다른 점은 쉘이 도트 파일 (이름이로 시작하는 파일)을 무시한다는 것 .입니다. 그것들을 bash에 포함 시키려면 먼저 설정하십시오 GLOBIGNORE=.:... zsh에서는 **/*(D)glob 패턴으로 사용하십시오.


이 답변 (및 Glenn의 답변)은에 주어진 질문에 대한 더 나은 답변 인 것 같습니다 sh -c.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.