오류가 발생하지 않도록 이 코드를 어떻게 변경할 수 있습니까? 즉, xargs
stdout이 비어 있으면 그 이후의 코드가 실행되지 않습니다.
단말기:
$ cat << EOF > dummy.sh
#! /usr/bin/env bash
[[ -f "\$1" ]] && echo "file=\$1" || { echo "error"; exit 1; }
shift
(( \$# == 0 )) || "\$0" "\$@"
EOF
$ chmod +x dummy.sh
$ mkdir trash.later && touch trash.later/foo
$ find trash.later -type f | xargs -n 1 ./dummy.sh
file=trash.later/foo
$ find trash.later -type f | grep 'bar' | xargs -n 1 ./dummy.sh
error
답변1
xargs
의 출력에는 사용 하지 마십시오 find
. xargs
기본적으로 입력 매개변수는 명령 출력이 없는 형식으로 구분되어야 하지만 물론 그렇지 않습니다 find
. 또한 출력을 find -print
안정적으로 사후 처리할 수 없습니다.
find
일종의 종교적으로 사용하는 유일한 방법 은 비표준 확장(원래는 GNU / 에서 왔지만 현재는 다른 많은 구현에서 발견됨)을 xargs
사용하는 것입니다 .-print0
-0
find
xargs
GNU에는 입력이 비어 있으면 명령을 실행하지 않는 / 확장 xargs
도 있습니다 ( NetBSD와 같은 일부 구현에서는 기본적으로 이를 수행합니다).-r
--no-run-if-empty
xargs
따라서 여기에서는 GNU find
// xargs
또는 grep
호환 장치를 사용하여 다음을 수행할 수 있습니다.
find trash.later -type f -print0 |
grep -z bar |
xargs -r -0 -n 1 ./dummy.sh
그러나 이는 표준에 비해 이점을 제공하지 않습니다.
find trash.later -path '*bar*' -type f -exec ./dummy.sh {} ';'
( 하려는 것처럼 파일 경로의 어느 곳에서나 -path '*bar*'
찾아보십시오 . 파일 이름 (경로의 마지막 구성 요소)만 찾는 것으로 바꾸십시오.)bar
grep bar
-name '*bar*'
bar
더 많은 관련 내용을 보려면 다음을 읽어보세요.찾기 결과를 반복하는 것이 왜 나쁜 습관입니까?
귀하의 질문에 대한보다 일반적인 대답으로 xargs
지원하지 않는 -r
구현 의 경우 해결 방법은 래퍼를 --no-run-if-empty
사용하는 것입니다 .sh
바꾸다:
... | xargs -n1 cmd
하다:
... | xargs sh -c 'for file do cmd "$file"; done' sh
입력이 없으면 계속 실행되지만 sh
인수 목록이 비어 있으므로 루프에 전달된 항목이 없으므로 cmd
실행되지 않습니다.
ifne
입력이 비어 있지 않은 경우에만 명령을 실행하는 명령 도 참조하세요.moreutils
... | ifne xargs -n1 cmd
그러나 입력이 비어 있지 않고 빈 줄만 포함하는 경우 ifne
실행되지만 해당 입력은 여전히 인수가 없는 것으로 간주되며 인수 없이 한 번만 실행됩니다(NetBSD 제외) xargs
.xargs
cmd
완전성을 위해
... | xargs -I {} cmd {}
cmd
입력이 비어 있거나 비어 있는 경우에도 실행되지 않습니다. 이 경우 입력을 인수로 분할하는 것은 다릅니다. 선행 공백이 제거되고 따옴표는 여전히 xargs
고유한 방식으로 처리되지만 그렇지 않으면 인수는 공백으로 구분된 단어가 아닌 전체 줄입니다.