xargs를 사용하여 여러 명령 실행

xargs를 사용하여 여러 명령 실행

find + xargs를 사용하여 여러 명령을 호출할 수 있습니까? 크기가 100자를 초과하는 모든 파일을 찾으려고 합니다. 1000자 미만인 경우 권한을 변경하고 파일 목록을 파일에 인쇄합니다. exec를 사용하여 이 작업을 수행할 수 있습니다.

find . -maxdepth 1 -size +100c -size -1000c -exec chmod a+r {} \; -print > testfile

그러나 xargs를 사용하여 이를 달성할 수 있는 방법이 있습니까?

   find . -maxdepth 1 -size +100c -size -1000c -print0 | xargs -0 -I '{}' chmod a+r '{}' -print >testfile

마지막 인쇄는 실행되지 않거나 오류가 발생합니다. xargs를 사용하여 이를 달성할 수 있는 방법이 있습니까?

답변1

-mindepth 1여기에는 GNUism이 필요하지 않으며( 제외 해야 할 수도 있음 ) 각 파일에 대해 하나씩 실행할 .필요가 없습니다 .chmod

find . ! -name . -prune ! -type l -size +100c -size -1000c -print \
  -exec chmod a+r {} + >testfile

( 변경 하면서 심볼릭 링크의 크기도 확인하기 ! -type l때문에 하나 추가했습니다.-sizechmod표적기호 링크이므로 기호 링크를 고려하는 것은 의미가 없습니다. 당신은 아마도 더 나아가서 고려하고 싶을 것입니다.정기적인문서( -type f))

표준 출력에는 아무 것도 출력되지 않기 때문에 여기서는 작동합니다 chmod(그렇지 않으면 테스트 파일에 출력됩니다).

보다 일반적으로 이를 방지하려면 다음을 수행해야 합니다.

find . ! -name . -prune ! -type l -size +100c -size -1000c -print -exec sh -c '
  exec cmd-that-may-write-to-stdout "$@" >&3 3>&-' sh {} + 3>&1 > testfile 

따라서 find의 stdout은 로 이동 testfile하지만 cmd-that-may-write-to-stdout의 stdout은 리디렉션 전에 원래의 stdout으로 이동합니다( 3>&1위에서 저장한 대로).

다음 사항에 유의하세요.

find . -maxdepth 1 -size +100c -size -1000c -exec chmod a+r {} \; -print > testfile

testfile성공한 파일을 포함합니다 chmod( -print다음은 -exec그에 -exec대한 또 다른 조건입니다 -print. -exec실행된 명령이 0이 아닌 종료 상태로 반환되면 성공합니다).

사용하려는 경우 xargs(여기서는 GNU 구문 사용) tee대체를 사용하고 처리할 수 있습니다.

 find . ! -name . -prune ! -type l -size +100c -size -1000c -print0 |
   tee >(tr '\0' '\n' > testfile) |
   xargs -r0 chmod a+r

findNUL의 출력을 개행 문자로 저장합니다 testfile. 하지만 이 tr명령은 백그라운드에서 실행된다는 점에 유의하세요 . 쉘은 기다리지만 (적어도 대부분의 쉘은 및 를 xargs기다리지만 ) 기다리지는 않습니다 . 따라서 쉘이 다음 명령을 실행할 때쯤에는 데이터 쓰기가 이미 완료되었을 가능성이 높습니다 . 그때까지 전체 쓰기가 모든 권한을 수정하는 것보다 더 중요 하다면 위의 및 명령을 바꾸는 것이 좋습니다 .teefindtrtrtestfiletestfilexargstr

또 다른 옵션은 위의 전체 코드를 다음과 같이 래핑하는 것입니다.

(<that-code>) 3>&1 | cat

이런 방식으로 쉘은 읽고 있는 파이프의 쓰기 측에서 파일 설명자 3이 열려 있는 모든 프로세스( , , , 포함)가 종료된 경우에만 cat기다리고 종료 됩니다.cattrfindteexargs

zsh또 다른 옵션은 여기서 glob을 사용하는 것입니다 .

files=(./*(L+100L-1000^@))
chmod a+r $files
print -rl $files > testfile

마주칠 수도 있지만너무 많이 논쟁하다파일 목록이 크면 오류가 발생합니다. find -exec +필요한 경우 xargs몇 가지 명령을 실행하여 이 문제를 해결할 수 있습니다. 이를 달성하기 위해 in을 사용할 수 있습니다.chmodzargszsh

관련 정보