xargs는 언제 필요합니까?

xargs는 언제 필요합니까?

xargs명령은 항상 나를 혼란스럽게 한다. 일반적인 규칙이 있나요?

다음 두 가지 예를 고려하십시오.

$ \ls | grep Cases | less

"Cases"와 일치하는 파일을 인쇄하지만 명령을 다음으로 변경하려면 다음이 touch필요합니다 xargs.

$ \ls | grep Cases | touch
touch: missing file operand
Try `touch --help' for more information.

$ \ls | grep Cases | xargs touch

답변1

차이점은 대상 프로그램에서 허용하는 데이터에 있습니다.

파이프만 사용하면 STDIN(표준 입력 스트림)의 데이터를 원시 데이터 묶음으로 수신하고 한 번에 한 행씩 정렬할 수 있습니다. 그러나 일부 프로그램은 표준 입력의 명령을 받아들이지 않으며 해당 명령의 인수에 해당 명령이 명시될 것으로 기대합니다. 예를 들어 touch다음과 같이 명령줄에서 파일 이름을 인수로 전달합니다 touch file1.txt.

파일 이름을 출력하는 프로그램이 있는 경우표준 출력그리고 그것들을 사용하고 싶어매개변수로이렇게 하려면 이를 touch사용 xargs하여 STDIN 스트림 데이터를 읽고 각 행을 명령에 대한 공백으로 구분된 인수로 변환해야 합니다.

이 두 가지는 동일합니다.

# touch file1.txt
# echo file1.txt | xargs touch

xargs해당 기능이 무엇인지, 왜 필요한지 정확히 알지 않는 한 사용하지 마세요. 종종 xargs캐스트를 사용하는 것보다 작업을 수행하는 더 좋은 방법이 있습니다 . 변환 프로세스에는 이스케이프 및 단어 확장과 같은 잠재적인 함정도 있습니다.

답변2

이미 제공된 답변을 확장하려면 xargs오늘날의 멀티 코어 및 분산 컴퓨팅 세계에서 점점 더 중요해지고 있는 멋진 일을 수행할 수 있습니다. 즉, 작업을 병렬로 처리할 수 있습니다.

예를 들어:

$ find . -type f -name '*.wav' -print0 |xargs -0 -P 3 -n 1 flac -V8

*.wav => *.flac( )을 인코딩하기 위해 세 가지 프로세스가 동시에 사용됩니다 -P 3.

답변3

xargs는 stdin에 파일 경로 목록이 있고 이에 대해 일부 작업을 수행하려는 경우 특히 유용합니다. 예를 들어:

$ git ls-files "*.tex" | xargs -n 1 sed -i "s/color/colour/g"

단계별로 확인해 보겠습니다.

$ git ls-files "*.tex"
tex/ch1/intro.tex
tex/ch1/motivation.tex
....

즉, 입력은 어떤 작업을 수행하려는 경로 목록입니다.

echo이러한 경로에 대해 xargs가 수행하는 작업을 이해하려면 다음과 같이 명령을 앞에 추가하는 것이 좋습니다 .

$ git ls-files "*.tex" | xargs -n 1 echo sed -i "s/color/colour/g"
sed -i "s/color/colour/g" tex/ch1/intro.tex
sed -i "s/color/colour/g" tex/ch1/motivation.tex
....

-n 1매개변수를 사용하면 xargs가 각 행을 자체 명령으로 변환합니다. 이 sed -i "s/color/colour/g"명령은 지정된 파일에 있는 모든 항목을 대체합니다 color.colour

이는 경로에 공백이 없는 경우에만 작동합니다. 이렇게 하는 경우 null로 끝나는 경로를 xargs에 대한 입력으로 사용하도록 플래그를 전달해야 합니다 -0. 사용 예는 다음과 같습니다.

$ git ls-files -z "*.tex" | xargs -0 -n 1 sed -i "s/color/colour/g"

위에서 설명한 것과 동일한 작업을 수행하지만 경로 중 하나에 공백이 있는 경우에도 작동합니다.

find이는 또는 와 같이 파일 이름을 출력으로 생성하는 모든 명령에 적용됩니다 locate. 많은 파일이 있는 git 저장소에서 이것을 사용한다면 다음과 같은 것 git grep -l대신에 이것을 사용하는 것이 더 효율적일 수 있습니다 git ls-files:

$ git grep -l "color" "*.tex" | xargs -n 1 sed -i "s/color/colour/g"

git grep -l "color" "*.tex"명령은 "color"라는 문구가 포함된 "*.tex" 파일 목록을 제공합니다.

답변4

xargsfind귀하의 예에서는 원하는 작업을 정확하게 수행하고 안전하게 수행하므로 전혀 사용할 필요가 없습니다 .

사용하려는 것은 정확히 다음과 같습니다 find.

find -maxdepth 1 -name '*Cases*' -exec touch {} +

이 경우 -maxdepth 1이는 하위 디렉터리로 깊이 들어가지 않고 현재 디렉터리에서만 검색한다는 의미입니다. maxlength로 제한하지 않는 한 find는 기본적으로 모든 하위 디렉터리를 검색합니다(일반적으로 원하는 것입니다). 은 {}그 자리에서 대체될 파일의 ​​이름이며 +두 개의 명령 종료 태그 중 하나입니다. 다른 하나는 입니다 ;. 차이점은 ;각 파일에 대해 명령을 한 번 실행한다는 의미이고, 다음 +명령을 실행한다는 의미입니다 . 모든 파일을 한 번에 명령합니다. 그러나 쉘이 스스로 해석하려고 시도할 수 있으므로 쉘을 사용하거나 이스케이프해야 한다는 점에 유의 ;하십시오 . 예, 이러한 작은 성가심이 많이 있지만 그 힘은 그것을 상쇄하고도 남습니다.\;';'find

둘 다 처음에는 배우기가 까다롭습니다 find. xargs학습에 도움이 되도록 또는 옵션을 xargs사용해 보십시오 . 이 옵션은 실행할 명령을 표시하고 실행할지 여부를 묻는 메시지를 표시합니다.-p--interactive

마찬가지로 대신 find를 사용하여 명령을 실행할지 여부를 묻는 메시지를 표시할 수도 있습니다.-ok-exec

하지만 때로는 find하고 싶은 일을 모두 할 수 없는 경우가 있는데, 이때가 xargs필요합니다. 이 -exec명령은 {}발생 사례를 하나만 허용하므로 사용 시 오류가 발생하는 경우 find -type f -exec cp {} {}.bak \;다음을 수행할 수 있습니다.find -type f -print0 | xargs -0 -l1 -IX cp X X.bak

다음에 대해 자세히 알아볼 수 있습니다.명령 실행내부에GNU Findutils 매뉴얼.

또한 파일을 처리할 때 또는 옵션을 사용하거나 null 종료 입력을 생성하지 않으면 find문제를 일으킬 수 있는 공백 및 기타 문자가 발생하기 때문에 원하는 대로 수행하는 것이 안전하다고 언급했습니다 . 내용이 비어 있습니다.xargs-0--null

관련 정보