이 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
xargs
find
귀하의 예에서는 원하는 작업을 정확하게 수행하고 안전하게 수행하므로 전혀 사용할 필요가 없습니다 .
사용하려는 것은 정확히 다음과 같습니다 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