문제
주어진 각 입력 라인에 대해 Xargs가 명령을 정확히 한 번 실행하도록하려면 어떻게해야합니까? 기본 동작은 선을 청소하고 명령을 한 번 실행하여 각 인스턴스에 여러 줄을 전달하는 것입니다.
에서 http://en.wikipedia.org/wiki/xargs:
/path -type f -print0 | XARGS -0 RM
이 예에서 찾기는 파일 이름의 긴 목록으로 XARG의 입력을 피드합니다. 그런 다음 Xargs는이 목록을 하위 목록으로 나누고 모든 하위 목록에 대해 RM을 한 번 호출합니다. 이것은 기능적으로 동등한 버전보다 더 효율적입니다.
/path -type f -exec rm '{}';
Find는 "Exec"플래그가 있다는 것을 알고 있습니다. 나는 단지 다른 리소스의 예시적인 예를 인용하고 있습니다.
해결책
다음은 입력에 공간이없는 경우에만 작동합니다.
xargs -L 1
xargs --max-lines=1 # synonym for the -L option
Man Page에서 :
-L max-lines
Use at most max-lines nonblank input lines per command line.
Trailing blanks cause an input line to be logically continued on
the next input line. Implies -x.
다른 팁
이 페이지의 모든 기존 답변은 올바른 것으로 표시된 것으로 보입니다. 그것은 질문이 모호하게 말한다는 사실에서 비롯됩니다.
요약: 명령을 실행하려면 "각 입력 라인마다 정확히 한 번," 전체 줄 (Newline없이)을 명령에 전달합니다. 단일 인수, 그런 다음 이것은 가장 유능한 호환 방법입니다.
... | tr '\n' '\0' | xargs -0 -n1 ...
암소 비슷한 일종의 영양 xargs
당신이 할 수있는 유용한 확장증이 있거나 없을 수도 있습니다. tr
, 그러나 OS X 및 기타 유닉스 시스템에서는 사용할 수 없습니다.
이제 긴 설명을 위해…
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
, 당신은 무엇이 필요합니까 xargs
을 위한?
노력하다:
find
길 -type f -exec
당신의 명령 {} \;
문자 그대로 {}
파일 이름과 리터럴로 대체됩니다 \;
필요합니다 find
사용자 정의 명령이 끝나는 것을 알기 위해.
편집하다:
(질문을 편집 한 후에 당신이 알고 있음을 명확히합니다. -exec
)
에서 man xargs
:
-엘 맥스 라인
최대를 사용하십시오 맥스 라인 명령 줄 당 비 블랭크 입력 라인. 후행 블랭크는 다음 입력 라인에서 입력 라인이 논리적으로 계속됩니다. -x를 의미합니다.
빈 공백으로 끝나는 파일 이름은 사용하면 문제가 발생합니다. xargs
:
$ mkdir /tmp/bax; cd /tmp/bax
$ touch a\ b c\ c
$ find . -type f -print | xargs -L1 wc -l
0 ./c
0 ./c
0 total
0 ./b
wc: ./a: No such file or directory
그래서 당신이 신경 쓰지 않는다면 -exec
옵션, 더 잘 사용합니다 -print0
그리고 -0
:
$ find . -type f -print0 | xargs -0L1 wc -l
0 ./c
0 ./c
0 ./b
0 ./a
주어진 각 입력 라인에 대해 Xargs가 명령을 정확히 한 번 실행하도록하려면 어떻게해야합니까?
나는 사용하지 않는다 -L 1
핵심 기능인 공간이있는 파일을 처리하지 않기 때문에 답변 find -print0
.
echo "file with space.txt" | xargs -L 1 ls
ls: file: No such file or directory
ls: space.txt: No such file or directory
ls: with: No such file or directory
더 나은 솔루션은 사용하는 것입니다 tr
신생을 null로 변환하기 위해 (\0
) 문자, 다음을 사용하십시오 xargs -0
논쟁.
echo "file with space.txt" | tr '\n' '\0' | xargs -0 ls
file with space.txt
그런 다음 통화 수를 제한 해야하는 경우 -n 1
각 입력에 대해 프로그램에 한 번 호출하는 인수 :
echo "file with space.txt" | tr '\n' '\0' | xargs -0 -n 1 ls
이것은 또한 찾기 출력을 필터링 할 수 있습니다. ~ 전에 파손을 널로 변환합니다.
find . -name \*.xml | grep -v /workspace/ | tr '\n' '\0' | xargs -0 tar -cf xml.tar
또 다른 대안 ...
find /path -type f | while read ln; do echo "processing $ln"; done
find path -type f | xargs -L1 command
필요한 전부입니다.
이 두 가지 방법은 또한 작동하며 찾기를 사용하지 않는 다른 명령에 효과가 있습니다!
xargs -I '{}' rm '{}'
xargs -i rm '{}'
예제 사용 사례 :
find . -name "*.pyc" | xargs -i rm '{}
PYC 파일에 공간이 포함 된 경우 에도이 디렉토리의 모든 PYC 파일을 삭제합니다.
다음 명령은 모든 파일 (-type f)을 찾을 수 있습니다. /path
그런 다음 사용하여 복사하십시오 cp
현재 폴더에. 사용 IF를 기록하십시오 -I %
에서 자리 표시 자 문자를 지정합니다 cp
파일 이름에 인수를 배치 할 수 있도록 명령 줄.
find /path -type f -print0 | xargs -0 -I % cp % .
Xargs (GNU findutils)로 테스트 4.4.0
각각--max-lines 또는--max-args 플래그를 사용하여 각각 라인 수 또는 인수 (각 인수 사이에 공백이있는 경우)를 제한 할 수 있습니다.
-L max-lines Use at most max-lines nonblank input lines per command line. Trailing blanks cause an input line to be logically continued on the next input line. Implies -x. --max-lines[=max-lines], -l[max-lines] Synonym for the -L option. Unlike -L, the max-lines argument is optional. If max-args is not specified, it defaults to one. The -l option is deprecated since the POSIX standard specifies -L instead. --max-args=max-args, -n max-args Use at most max-args arguments per command line. Fewer than max-args arguments will be used if the size (see the -s option) is exceeded, unless the -x option is given, in which case xargs will exit.
의견을 추가 할 충분한 평판이없는 것 같습니다. 위의 토비아의 답변, 그래서 나는 우리가 실험하고자하는 사람들을 돕기 위해이 "답변"을 추가하고 있습니다. xargs
Windows 플랫폼에서도 같은 방식으로.
다음은 Tobia의 빠르게 코딩 된 "Show"스크립트와 동일한 작업을 수행하는 Windows 배치 파일입니다.
@echo off
REM
REM cool trick of using "set" to echo without new line
REM (from: http://www.psteiner.com/2012/05/windows-batch-echo-without-new-line.html)
REM
if "%~1" == "" (
exit /b
)
<nul set /p=Args: "%~1"
shift
:start
if not "%~1" == "" (
<nul set /p=, "%~1"
shift
goto start
)
echo.
@draemon 답변은 파일의 공간이 있어도 "-0"에 맞는 것 같습니다.
나는 Xargs 명령을 시도했고 "-0"이 "-l"과 완벽하게 작동한다는 것을 알았습니다. 공간조차 처리됩니다 (입력이 종료 된 경우). 다음은 예입니다.
#touch "file with space"
#touch "file1"
#touch "file2"
다음은 널을 분할하고 목록의 각 인수에서 명령을 실행합니다.
#find . -name 'file*' -print0 | xargs -0 -L1
./file with space
./file1
./file2
그래서 -L1
"-0"과 함께 사용하면 각 널 종료 된 문자에 대한 인수를 실행합니다. 차이를 보려면 시도 :
#find . -name 'file*' -print0 | xargs -0 | xargs -L1
./file with space ./file1 ./file2
조차도 한 번 실행됩니다.
#find . -name 'file*' -print0 | xargs -0 | xargs -0 -L1
./file with space ./file1 ./file2
"-L"이 이제 NULL 바이트에서 분할되지 않으므로 명령이 한 번 실행됩니다. 작동하려면 "-0"과 "-l"을 모두 제공해야합니다.
예에서 찾기 출력을 XARGS로 배관하는 점은 Find의 -Exec 옵션의 표준 동작이 각 파일에 대해 명령을 한 번 실행하는 것입니다. Find를 사용하고 있으며 표준 동작을 원한다면 대답은 간단합니다. Xargs를 사용하여 시작하지 마십시오.
현재 또는 하위 폴더에서 모든 Build.xml에서 ANT 작업을 클린 작업을 실행하십시오.
find . -name 'build.xml' -exec ant -f {} clean-all \;