pipeline, 또 다시 한번 도전: xargs 사용법.

습관으로, 그저 손가락 근육이 기억하는대로 파이프(라인)을 써왔다. Redirection 도 마찬가지.

오늘, 쓰잘 데없어보이나, 결코 쓰잘 데 없지는 않은, 뭔가를 하다가 파이프의 벽에 또 부딪혔다.
자, 아래 명령이 왜 내가 원하는대로 되지 않을까?

$ find . -type f | cat
./deleteme.txt
./config.cson
./github.cson
./init.coffee
./keymap.cson
./nohup.out
./package-deps-state.json

내가 원했던 건, 파일명을 나열하는 게 아니고, ‘파일 내용 출력’ 이었다. 어디가 잘못된 걸까?

find . -type f 명령은, 그 결과를 텍스트로 출력을 한다. 물론, 그 결과값이 ‘경로’의 형식을 띠고는 있으나, 디렉토리를 뜻하지는 않고, 그냥 문자열일 뿐이다.
또, cat 의 man page 에는 이런 내용이 초반부에 나와있다.

DESCRIPTION
       Concatenate FILE(s) to standard output.

       With no FILE, or when FILE is -, read standard input.

파이프로 넘어온 데이터는 Standard Input 이고, 그냥 문자열이다. 따라서 cat 은 받은 문자열을 그대로 출력해주는 역할 밖에 하지 못한다.
그냥 간단히 생각을 해본다면, cat ./deleteme.txt 이 되어 이 파일을 출력해줄 듯 한데, cat 은 이걸 파일명으로 인식하지 못한다.
즉, 아래 두 명령은 같은 결과를 보여준다.

$ find . -type f | cat
$ find . -type f | cat -

파이프라인을 쓸 때는 ‘-‘ 기호를 써서, Standard Input 임을 명시한 결과와 그냥 cat 만 쓴 결과가 같다.
cat 만 이런게 아니고, sed, awk 모두 같은 결과를 보여준다. find 결과로 받은 것은 ‘문자열’이지, ‘경로’가 아니다.

‘문자열’을 ‘경로’로 인식하게 해주려면??? 자, 뭘 어떻게 해야 되는거냐??

여기서 xargs 가 등장한다.

$ find . -type f | xargs cat

이제 내가 원했던 결과를 얻을 수 있게 됐다.
xargs 의 형식은 다음과 같다.

xargs [options] [command [initial-arguments]]

위 명령을 해석해보자면, find 결과를 Standard Input 으로 받아서, 그걸 일련의 리스트로 만든 뒤, 뒤에 나오는 command, 즉 cat 에 인수로 넘겨준다.
cat 은 이때 넘겨받은 인수를, Standard Input 이 아닌, 일반 인수, 즉 경로로 인식을 한다.

왜?? 그런 지는 모르겠다. 어떨 때는 Std. Input 이고, 어떨 때는 경로가 된다.
그냥, 이렇게 이해하자. 아니, 그냥 외우자.

  • Pipeline : 그 결과는 무조건 Standard Input, 즉 문자열이다.
  • xargs : Standard Input 을 받아서, 다른 명령의 인수로 넘긴다. 따라서 결과는 문자열일 수도, 경로일 수도 있다.

따라서, ‘경로’가 필요할 때는 무조건 xargs 를 쓴다. 이것만 외우면 되겠다.

여기까지는 전초전, 본 게임은 이 글 다음에 이어진다.
원하는 건 이런 거다.

‘텍스트 파일을 찾아서, 그 안에 특정 문자열이 포함되어 있는 지 확인한다.’
‘때에 따라서, 조건에 부합되는 파일명만을 원할 수도 있고, 직접 문자열 치환을 할 수도 있다.’

이게 간단해 보이면서, 또 그렇지 않은 일이다.
과연??

2 Comments

안녕하세요. 글 남겨주셔서 고맙습니다.