이 페이지의 모든 기존 답변이 올바른 것으로 표시된 답변을 포함하여 잘못된 것 같습니다. 그것은 질문이 모호하게 표현되어 있다는 사실에서 비롯됩니다.
요약 : 명령을 "한 줄씩 입력 할 때마다 정확히 한 번" 명령을 실행하려면 전체 행 (줄 바꿈없이)을 단일 인수 로 명령에 전달 하면 가장 적합한 UNIX 호환 방법입니다.
... | tr '\n' '\0' | xargs -0 -n1 ...
GNU xargs
는 유용한 확장 기능을 가지고 있거나 가지고 있지 않을 수도 tr
있지만 OS X 및 기타 UNIX 시스템에서는 사용할 수 없습니다.
이제 긴 설명을 위해…
xargs를 사용할 때 고려해야 할 두 가지 문제가 있습니다.
- 입력을 "인수"로 어떻게 분할합니까? 과
- 한 번에 자식 명령을 전달할 인수 수
xargs의 동작을 테스트하려면 실행 횟수와 인수 수를 보여주는 유틸리티가 필요합니다. 표준 유틸리티가 있는지 모르겠지만 bash에서 쉽게 코딩 할 수 있습니다.
#!/bin/bash
echo -n "-> "; for a in "$@"; do echo -n "\"$a\" "; done; echo
show
현재 디렉토리에 파일 을 저장하고 실행 가능 하다고 가정하면 다음과 같이 작동합니다.
$ ./show one two 'three and four'
-> "one" "two" "three and four"
이제 원래의 질문이 실제로 포인트 2에 관한 것이라면 (제 생각에 몇 번 이상 읽은 후) 다음과 같이 읽습니다 (굵게 변경).
주어진 입력 인수 마다 xargs가 명령을 정확히 한 번만 실행하도록하려면 어떻게 해야합니까? 기본 동작은 입력을 인수 로 청크하고 가능한 한 적은 수의 명령 을 실행하여 각 인스턴스에 여러 인수 를 전달하는 것 입니다.
대답은 -n 1
입니다.
xargs의 기본 동작을 비교하여 입력을 공백으로 나누고 명령을 가능한 한 적게 호출합니다.
$ echo one two 'three and four' | xargs ./show
-> "one" "two" "three" "and" "four"
그리고 그것의 행동 -n 1
:
$ echo one two 'three and four' | xargs -n 1 ./show
-> "one"
-> "two"
-> "three"
-> "and"
-> "four"
반면에 원래의 질문이 포인트 1에 관한 것이었고 입력 분할과 같이 읽히는 경우 (여기에 오는 많은 사람들이 그런 경우라고 생각하거나 두 가지 문제를 혼란스럽게합니다) :
xargs가 주어진 각 입력 행에 대해 정확히 하나의 인수 로 명령 을 실행하도록하려면 어떻게 해야합니까? 기본 동작은 공백 주위 의 행을 청크하는 것 입니다.
대답은 더 미묘합니다.
-L 1
도움이 될 수 있다고 생각 하지만 인수 구문 분석을 변경하지는 않습니다. 각 입력 행에 대해 한 번만 명령을 실행하며 해당 입력 행에있는 수만큼의 인수를 사용합니다.
$ echo $'one\ntwo\nthree and four' | xargs -L 1 ./show
-> "one"
-> "two"
-> "three" "and" "four"
뿐만 아니라 줄이 공백으로 끝나면 다음 줄에 추가됩니다.
$ echo $'one \ntwo\nthree and four' | xargs -L 1 ./show
-> "one" "two"
-> "three" "and" "four"
분명히, -L
에 대한 방법 xargs를 변경하지 않는 것은 인수로 입력을 분할합니다.
크로스 플랫폼 방식 (GNU 확장명 제외)으로 그렇게하는 유일한 인수 -0
는 입력을 NUL 바이트로 분할하는 것입니다.
그런 다음 도움을 받아 줄 바꿈을 NUL로 변환하는 것입니다 tr
.
$ echo $'one \ntwo\nthree and four' | tr '\n' '\0' | xargs -0 ./show
-> "one " "two" "three and four"
이제 인수 구문 분석은 후행 공백을 포함하여 올바르게 보입니다.
마지막 으로이 기술을와 결합하면 -n 1
입력 줄마다 정확히 하나의 명령 실행이 발생합니다. 입력에 관계없이 원래 질문을 볼 수있는 또 다른 방법 일 수 있습니다 (제목이 주어지면 가장 직관적 일 수 있습니다).
$ echo $'one \ntwo\nthree and four' | tr '\n' '\0' | xargs -0 -n1 ./show
-> "one "
-> "two"
-> "three and four"
find /path -type f -delete
훨씬 더 효율적일 것입니다 :)