XARGS가 각 입력 라인에 대해 명령을 한 번 실행하십시오.

StackOverflow https://stackoverflow.com/questions/199266

  •  11-07-2019
  •  | 
  •  

문제

주어진 각 입력 라인에 대해 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를 사용할 때 고려해야 할 두 가지 문제가 있습니다.

  1. 입력을 "인수"로 어떻게 분할합니까? 그리고
  2. 한 번에 아동 명령을 전달할 논쟁이 몇 개나 있습니다.

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 \;
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top