서로 다른 두 명령의 결과를 단일 명령으로 병합하고 파이프하는 방법은 무엇입니까?


34

두 개의 다른 명령에서 병합 (결합) 출력을 원하고 단일 명령으로 파이프하고 싶습니다.

어리석은 예 :

출력을 병합하고 싶은 명령 :

cat wordlist.txt
ls ~/folder/*

으로:

wc -l

이 예에서 wordlist.txt에 5 줄과 3 개의 파일이 wc -l있으면 8을 반환 하려고 합니다.

$cat wordlist.txt *[magical union thing]* ls ~/folder/* | wc -l
8

어떻게합니까?

답변:


55

당신의 마법의 연합 은 세미콜론과 중괄호입니다.

    { cat wordlist.txt ; ls ~/folder/* ; } | wc -l

중괄호는 명령 만 그룹화하므로 파이프 부호 |가 결합 된 출력에 영향을줍니다.

()명령 그룹 주위에 괄호 를 사용 하여 서브 쉘에서 명령을 실행할 수도 있습니다 . 이것은 중괄호와 미묘한 차이가 있습니다. 예를 들어 다음을 시도하십시오.

    cd $HOME/Desktop ; (cd $HOME ; pwd) ; pwd
    cd $HOME/Desktop ; { cd $HOME ; pwd ; } ; pwd

현재 작업 디렉토리를 포함한 모든 환경 변수가 괄호 그룹을 종료 한 후 재설정되지만 중괄호 그룹을 종료 한 후에는 재설정되지 않습니다.

세미콜론의 경우, 대안은 &&||부호를 포함하며 , 첫 번째가 성공하거나 그렇지 않은 경우에만 두 번째 명령을 조건부로 실행합니다. 예 :

    cd $HOME/project && make
    ls $HOME/project || echo "Directory not found."

1
작동합니다! 학습 도움-여기서 중괄호는 정확히 무엇을합니까? 그들은 어떤 다른 마법의 힘을 가지고 있습니까?
David Oneill

@DavidOneill { list; }복합 명령 입니다. From bash(1): list는 현재 쉘 환경에서 간단하게 실행됩니다. 리스트는 개행 또는 세미콜론으로 끝나야합니다. [..] 반환 상태는 list의 종료 상태입니다.
Lekensteyn

답변에 약간 더 많은 정보를 추가했습니다. bash를 사용한 쉘 스크립팅에 대한 확실한 안내서는 bash 맨 페이지이며 man bash명령 줄에서 입력 하고 찾아보십시오.
pablomme

해야한다; wordlist.txt 파일이없는 경우 해당 명령에서 &&가 될 수 없습니까?
Rinzwind

wordlist.txt존재하지 않는 경우 cat표준 오류에는 오류가 표시되지만 표준 출력에는 표시 되지 않으므로 오류가 발생하지 않습니다 wc -l. ~/folder존재하지 않는 것도 마찬가지입니다 . 2> /dev/null각 명령과 세미콜론 사이에 표준 오류에 대한 노이즈를 방지하기 위해 추가 할 수 있지만, 추악한 것 이외의 오류 메시지는 라인 수를 계산하는 데 무해합니다.
pablomme

8

wc파일 경로를 입력으로 받아들이 므로 프로세스 대체를 사용할 수도 있습니다.

wc -l <(cat wordlist.txt; ls ~/folder/*)

이것은 대략 다음과 같습니다.

echo wordlist.txt > temp
ls ~/folder/* >> temp
wc -l temp

ls ~/folder/*하위 디렉토리의 컨텐츠가있는 경우이를 리턴하는 마음 (글로브 확장으로 인해). 의 내용 만 나열하려면을 ~/folder사용하십시오 ls ~/folder.


이것은 wc -l단지 구성 된 예제였습니다. 실제로이 옵션이없는 더 복잡한 것으로 파이프하고 있습니다.
David Oneill

2
@DavidOneill 음, cat파일 인수 를 허용하므로 cat <(cat wordlist.txt; ls wordlist.txt) | wc -l및 을 사용할 수 있습니다 cat wordlist.txt <(ls wordlist.txt) | wc -l. 이것은 물론 추악하지만 명령 줄 도구를 사용하여 끝없는 가능성을 보여줍니다.
Lekensteyn

1
@DavidOneill Correct, 고마워 지금 고쳤습니다.
Lekensteyn

1
당신이 원하는 ls ~/folder/경우 너무 ~/folder입니다 심볼릭 링크가 ls목표의 내용이 아닌 링크 자체를 보여줍니다. 그건 그렇고, 모든 ls명령 뒤에 -1줄 당 하나의 파일이 인쇄되고 wc -l파일을 계산하는 올바른 방법이 있어야합니다.
pablomme

@pablomme symlink에 대해서는 사실이지만 -1출력은 터미널이 아니라 파이프이므로 암시됩니다.
Lekensteyn

2

나는 나 자신에게 같은 질문을하고 짧은 스크립트를 작성했다.

magicalUnionThing(나는 그것을 부른다 append) :

#!/bin/sh
cat /dev/stdin
$*

해당 스크립트를 실행 가능하게 만들기

chmod +x ./magicalUnionThing

이제 제대로 하는군

cat wordlist.txt |./magicalUnionThing ls ~/folder/* | wc -l

그것이하는 일 :

  • 표준 입력을 표준 출력으로 전송
  • 인수를 실행하십시오. $*모든 인수를 문자열로 반환합니다. 해당 명령의 출력은 기본적으로 스크립트 표준 출력으로 이동합니다.

따라서 magicalUnionThing의 표준 출력은 인수로 전달되는 명령의 표준 입력 + 표준 출력이됩니다.

물론 다른 답변에 따라 더 간단한 방법이 있습니다.
경우에 따라이 대안이 유용 할 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.