터미널에 익숙한 사용자일수록 더 똑똑하게, 그리고 더 적은 노력으로 작업을 처리하는 새로운 방법을 끊임없이 찾게 됩니다. xargs는 바로 그런 목적에 딱 맞는 유용한 명령어입니다. 이 명령은 두 명령 사이의 다리 역할을 하며, 한 명령의 출력 결과를 읽어 들여 그 항목들을 다른 명령의 입력으로 전달하고 실행합니다. 주로 특정 패턴 검색, 파일 삭제 및 이름 변경 등의 상황에서 널리 사용됩니다. 이 글에서는 xargs 명령어를 효과적으로 활용하는 다양한 방법을 소개합니다.
xargs란 무엇인가?
기본 형태로 xargs는 표준 입력(STDIN)으로부터 정보를 읽어 들인 후, 읽어 온 항목들을 인수로 삼아 지정된 명령을 한 번 이상 실행합니다. 간단한 예제는 여러 가지가 있지만, 다음 예시를 통해 개념을 쉽게 이해할 수 있습니다.
예를 들어 xargs를 이용해 Documents 폴더에 ls 명령을 실행하려면 아래와 같이 입력합니다.
echo "Documents" | xargs ls
여기서 파이프 문자 |는 앞선 명령의 출력을 xargs의 표준 입력으로 전달하는 역할을 합니다.
실행 결과를 보면 xargs가 Documents 폴더를 문제없이 읽어 온 것을 확인할 수 있습니다. 이것은 xargs 명령어가 할 수 있는 일 중 극히 일부에 불과합니다.
xargs는 다양한 명령줄 작업에 활용할 수 있지만, 특히 find 명령과 함께 사용할 때 진가를 발휘합니다. 이 글에서는 xargs와 find를 조합하는 실용적인 예제들을 살펴보겠습니다.
여러 파일을 한 번에 다루는 작업
특정 디렉터리에 있는 모든 텍스트 파일에 "ref.txt"의 내용을 복사하고 싶다고 가정해 보겠습니다. 평소라면 여러 번 명령을 반복 실행해야겠지만, xargs와 find를 조합하면 단 한 줄로 해결됩니다. 테스트 디렉터리가 두 개 있다고 해봅시다. 하나에는 내용이 있는 "test0.txt"가 있고, 다른 디렉터리에는 내용이 없는 테스트 파일 10개가 들어 있습니다. test0.txt의 내용을 나머지 텍스트 파일들에 모두 복사하려면 다음 명령을 실행합니다.
find ./test-dir1/ -name "*.txt" | xargs -n1 cp test0.txt
위 명령을 이해하기 위해 두 부분으로 나누어 살펴보겠습니다.
첫 번째 부분인 find ./test-dir1/ -name "*.txt"는 "test-dir1" 디렉터리 안의 모든 .txt 파일을 찾습니다. 물론 원하는 어떤 디렉터리든 지정할 수 있습니다.
두 번째 부분인 xargs -n1 cp test0.txt는 첫 번째 명령의 출력 결과(찾아낸 파일 이름들)를 받아 cp(복사) 명령에 하나씩 전달합니다. 여기서 -n 옵션이 매우 중요한데, 이 옵션은 xargs에게 실행당 인수를 하나씩만 사용하도록 지시하기 때문입니다.
두 부분이 결합되면 전체 명령은 "test0.txt"의 내용을 해당 디렉터리의 모든 .txt 파일에 복사하게 됩니다.
대량의 인수를 처리하는 작업
xargs의 가장 큰 장점 중 하나는 방대한 수의 인수를 처리할 수 있다는 점입니다. 예를 들어 파일을 한꺼번에 대량 삭제할 때 rm 명령이 가끔 "Argument list too long(인수 목록이 너무 깁니다)" 오류를 내며 실패하는 경우가 있습니다. 이는 명령이 감당할 수 있는 인수 목록의 길이를 초과했기 때문입니다. 삭제하려는 폴더에 파일이 지나치게 많을 때 흔히 발생하는 상황입니다.
예를 들어 PDF 파일 75개를 삭제하려다 오류가 발생했다고 가정해 보겠습니다.
이런 문제는 xargs로 아주 간단히 해결할 수 있습니다. 모든 PDF 파일을 삭제하려면 다음 명령을 사용하세요.
find ./test-dir2/ -type f -name "*.pdf" -print | xargs rm -f
패턴 검색 작업
소프트웨어 개발자와 시스템 관리자는 명령줄에서 패턴 검색 작업을 자주 수행합니다. 예를 들어 개발자는 특정 변수를 수정하는 프로젝트 파일을 빠르게 확인하고 싶을 수 있고, 시스템 관리자는 특정 시스템 설정 파라미터를 사용하는 파일을 찾고 싶을 수 있습니다. 이럴 때 xargs를 find와 grep과 함께 사용하면 작업이 한결 수월해집니다.
예를 들어 "maketecheasier"라는 문자열을 포함하는 모든 .txt 파일을 검색하려면 다음 명령을 실행합니다.
find ./ -name "*.txt" | xargs grep "maketecheasier"
필자의 시스템에서 위 명령을 실행했을 때 출력된 결과는 다음과 같습니다.
파일 잘라내기/복사 작업
xargs는 find 명령과 조합해 여러 파일을 한 디렉터리에서 다른 디렉터리로 복사하거나 이동하는 데도 활용할 수 있습니다. 예를 들어 현재 디렉터리에서 10분 이상 지난 텍스트 파일을 모두 상위 디렉터리로 이동하려면 다음 명령을 사용합니다.
find . -name "*.txt" -mmin +10 | xargs -n1 -I '{}' mv '{}' ../
-I 명령줄 옵션은 xargs가 치환 문자열(replace-string)을 정의할 때 사용합니다. 이 치환 문자열은 find 명령의 출력에서 읽어 온 파일 이름으로 대체됩니다. 위 예제에서 치환 문자열은 {}이지만, 사실 어떤 문자열이든 사용할 수 있습니다. 예를 들어 "file"이라는 문자열을 치환 문자열로 쓸 수도 있습니다.
find . -name "*.txt" -mmin +10 | xargs -n1 -I 'file' mv 'file' ./practice
xargs의 실행 시점 제어하기
현재 디렉터리에 있는 모든 .txt 파일의 상세 정보를 출력하고 싶다고 가정해 보겠습니다. 앞서 설명한 대로 다음 명령으로 손쉽게 처리할 수 있습니다.
find . -name "*.txt" | xargs ls -l
그런데 여기에는 한 가지 문제가 있습니다. find 명령이 .txt 파일을 하나도 찾지 못했는데도 xargs는 어김없이 ls 명령을 실행한다는 점입니다. 실제 예시는 다음과 같습니다.
디렉터리에 .txt 파일이 전혀 없음에도 불구하고 xargs가 ls 명령을 실행한 것을 확인할 수 있습니다. 이러한 동작을 바꾸려면 -r 명령줄 옵션을 사용하세요. 이 옵션을 추가하면 입력이 없을 경우 명령을 아예 실행하지 않습니다.
find . -name "*.txt" | xargs -r ls -l
마무리
이 글에서는 xargs를 find와 함께 사용하는 방법에 초점을 맞췄지만, 사실 xargs는 그 밖의 수많은 명령과도 조합할 수 있습니다. 여러 단계로 이루어진 복잡한 명령을 실행해야 할 때 xargs는 매우 강력한 도구가 되어 줍니다.
리눅스에서 xargs 명령어를 활용하는 방법에 대한 이 글이 도움이 되었다면, "no space left on device" 오류 해결법이나 우분투 속도 개선 가이드 같은 다른 리눅스 관련 콘텐츠도 함께 확인해 보시기 바랍니다.