![입력 목록이 제공된 각 입력에 대해 명령을 실행하는 방법](https://linux55.com/image/37070/%EC%9E%85%EB%A0%A5%20%EB%AA%A9%EB%A1%9D%EC%9D%B4%20%EC%A0%9C%EA%B3%B5%EB%90%9C%20%EA%B0%81%20%EC%9E%85%EB%A0%A5%EC%97%90%20%EB%8C%80%ED%95%B4%20%EB%AA%85%EB%A0%B9%EC%9D%84%20%EC%8B%A4%ED%96%89%ED%95%98%EB%8A%94%20%EB%B0%A9%EB%B2%95.png)
여러 개의 폴더가 있고 각 폴더에 CD를 넣고 명령을 실행하고 싶습니다. 나는 이것이 다음과 같아야 한다고 생각합니다.
(다음은 제가 하고 싶은 일을 인위적으로 단순화한 예입니다.)
ls | xargs echo 'Looking at {}' && cd {} && /bin/do_stuff
그러나 이것은 작동하지 않습니다. 어떻게 해야 하나요?
답변1
xargs
명령이 직접 실행되기 때문에 작동하지 않습니다 . 이는 한 줄의 셸 코드도 허용하지 않으며 실행을 위해 명령을 셸에 전달합니다. 사실, 이 모든 &&
는 쉘에 의해 해석됩니다앞으로 ls
달리는 것조차 xargs
. 또한 은 {}
이해하기 쉬운 구조 find
입니다 xargs
.
( 원하는 경우 -I
with를 사용하여 xargs
이 기능을 흉내낼 수 있습니다 find
.)
가장 쉬운 방법 xargs
은 명령을 쉘 스크립트에 넣는 것입니다.
#!/bin/sh
echo "Looking at $1"
cd $1
/bin/do_stuff
( 다른 하위 디렉터리만 포함하는 디렉터리에서 실행하는 한 실패하지 않을 것처럼 보이고 실패하지 않기 때문에 이를 실제로 대체했습니다. "and" 동작이 필요한 경우 스크립트에 필요한 수정 사항 은 명백 &&
합니다 . .);
echo
cd
그런 다음 쉘 스크립트를 실행하십시오 xargs
. 당신이 그것을 호출하는 경우 dostuff.sh
:
$ ls | xargs ./dostuff.sh
dostuff.sh
처럼 실행 가능으로 표시되어야 합니다 chmod +x dostuff.sh
.
아마도 이 모든 것을 한 줄에 쓸 수 있는 방법이 있을 것입니다 sh -c
. 그러나 이런 일을 하는 마법을 기억하지 못한다면 그것은 대부분 단지 호기심일 뿐이지 않습니까?
답변2
xargs
올바른 도구이지만 사용하기가 어렵습니다.
xargs
당신이 지시하지 않는 한 쉘을 실행하지 마십시오. 옵션이 아닌 첫 번째 인수에 지정된 명령을 실행하고 명령줄에 추가 인수를 전달한 다음 표준 입력에서 읽은 인수를 전달합니다. 예를 들어
echo hello world | xargs echo 'Looking at'
달리다 echo 'Looking at' hello world
. 입력 줄당 한 번씩 명령을 실행하려면 다음을 사용하십시오 xargs -L1
.
(echo hello; echo world) | xargs -L1 echo 'Looking at'
쉘 명령을 실행 하려면 xargs
명시적으로 쉘을 호출하도록 해야 합니다.
(echo hello; echo world) | xargs sh -c 'echo "Looking at $0" && cd "$0" && /bin/do_stuff'
(아니면 tcsh -c
정말 하고 싶지만 지금은 21세기입니다.)
명령 내에서 보간법을 사용할 수 있지만 -I {}
이는 입력에 셸 특수 문자가 포함되지 않은 경우에만 작동한다는 점에 유의하세요. {}
입력을 명령( $0
위)에 인수로 전달하는 이점은 입력에 대해 가정이 이루어지지 않는다는 것입니다(구문에 따라 줄로 구분되고 후행 공백을 포함하지 않는다는 점 제외 xargs -L
).
Bourne/POSIX 스타일 셸에서 더 많은 라인을 사용하면서도 더 깔끔하게 만드는 또 다른 방법은 셸 내장 함수 주위에 루프를 사용하는 것입니다 read
.
{ echo hello; echo world; } |
while IFS= read -r line; do
echo "Looking at $line"
(cd "$line" && /bin/do_stuff)
done
( cd
전체 루프가 동일한 셸에서 실행되기 때문에 하위 셸에서 실행하고 있으며 해당 셸의 작업 디렉터리를 변경하고 싶지 않습니다.)