본문 바로가기

쉘스크립트/xargs

xargs

xargs 명령은 두개 이상의 명령어를 조합할 때 아주 요긴하다.

앞 명령어의 결과를 다음 명령어의 입력으로 넘기는 파이프(|)와 함께 사용함으로써, 앞 명령어의 출력값을 다음 명령어의 인자(argument)로 넘길  수 있기 때문이다.

 

예제

1. ls 명령으로 파일 목록을 출력하고, 해당 목록에서 .bak 파일만 골라서 rm 명령으로 삭제

# .bak 파일 확인
ls | grep "\.bak$"

# .bak 파일을 rm 명령으로 삭제
ls | grep "\.bak$" | xargs rm

ls와 grep의 조합으로 삭제할 대상 파일명을 추려낸 후에
이것을 rm 명령의 인자로 넘기는  것이다.

별도의 옵션이 없을 경우 이전 명령에 의한 출력값은
xargs 명령에서 가장 끝으로 가게 된다는 점에 유의하자.

2. 때에따라 인자의 위치를 명시적으로 지정해야 할 필요가 있다.

cp 명령어가 대표적인데, 예를들어 ls와 grep으로 추려낸 .bak 파일을 /bak_files 디렉토리에 복사하는 경우이다.

오류사례

# .bak 파일 복사 시도: 오류 발생!

ls | grep "\.bak$" | xargs cp ./bak_files

cp: missing destination file operand ... 
Try 'cp --help' for more information.

위에 코드의 문제는 출력값이 cp 명령에서 맨 끝이 아니라 중간에 인자로 들어가야 하기 때문이다.

이럴 경우에는 -i 또는 -I 옵션을 이용해서 출력값을 어느 위치에서 인자로 사용할 것인지 지정해 주면 된다.

성공사례

# -I 옵션으로 .bak 파일 복사 시도: 성공!
ls | grep "\.bak$" | xargs -I{} cp {} ./bak_files

# -i 옵션으로 .bak 파일 복사 시도: 성공!
ls | grep "\.bak$" | xargs -i cp {} ./bak_files

위의 예시를 보면 grep 명령의 출력값이 이어지는 cp 명령에서 "{}" 문자열로 지정한 자리에 위치하게 되어 복사가 정상적으로 이루어지게 된다.
xargs 매뉴얼(man) 페이지에 의하면 -i 옵션은 옛날 방식이므로 -I 옵션을 사용하도록 권고하고 있다.
-i 옵션에서 아무것도 지정하지 않을 경우 기본값으로 "{}" 문자열이 사용되고, -I 옵션에는 기본값이 없으므로 반드시 -I{} 이런 식으로 사용해야 한다.

위치 지정 문자열은 편의에 따라 적당히 바꿔서 사용할 수도 있다. 아래의 예시는 "{}" 때신 "FILE" 문자열을 사용한 경우다.

# -I 옵션
ls | grep "\.bak$" | xargs -IFILE cp FILE ./bak_files

# -i 옵션
ls | grep "\.bak$" | xargs -iFILE cp FILE ./bak_files

예시사례

홈 디렉토리(~/) 하위에서 .txt 파일만 추려낸 후, 이 중에 문자열 "abcd"를 포함하고 있는 파일이 어느 것인지 찾는 방법

find ~/ -type f | grep "\.txt$" | xargs grep -H "abcd"