답변:
명령 대체 `…`
는 명령 출력을 명령 행으로 대체하므로 diff
두 디렉토리의 파일 목록을 인수로 봅니다. 원하는 것은 diff
명령 행에서 두 개의 파일 이름을보고이 파일의 내용을 디렉토리 목록으로 만드는 것입니다. 그것이 프로세스 대체 가하는 일입니다.
diff <(ls old) <(ls new)
인수 diff
는 다음 /dev/fd/3
과 /dev/fd/4
같습니다. 이들은 bash가 작성한 두 개의 파이프에 해당하는 파일 디스크립터입니다. 때 diff
이러한 파일을 열고, 그것은 각 파이프의 읽기 측에 연결됩니다. 각 파이프의 쓰기면이 ls
명령에 연결됩니다 .
echo <(echo) <(echo)
이게 너무 재미있을 줄은
ls
는 파일 이름을 엉망으로 만든다는 것 입니다. 출력 파싱은 취약합니다 ( "이상한"파일 이름에서는 작동하지 않습니다). 두 디렉토리 목록을 비교할 때 출력이 모호하지 않는 한 괜찮습니다. 임의의 파일 이름을 사용하려면와 같은 옵션이 필요합니다 --quoting-style=escape
.
<(…)
은 파이프를 만듭니다. meld는 파이프와 함께 작동하지 않으므로 사용할 수 없습니다 <(…)
. zsh을, 당신은 대체 할 수 <(…)
로 =(…)
하고 있기 때문에 작동 =(…)
임시 파일에 중간 출력을 넣습니다. bash에서는 편리한 구문이 없다고 생각합니다. 임시 파일을 직접 관리해야합니다.
zsh의 경우를 사용하면 =(command)
자동으로 임시 파일이 작성 =(command)
되고 파일 자체의 경로로 대체 됩니다. 명령 대체를 사용하면 명령 출력 으로 $(command)
대체됩니다 .
따라서 세 가지 옵션이 있습니다.
$(...)
<(...)
=(...)
zsh flavored process subsitution # 3은 매우 유용하며 diff 도구를 사용하여 두 명령의 출력을 비교하는 데 사용할 수 있습니다 (예 : Beyond Compare).
bcomp =(ulimit -Sa | sort) =(ulimit -Ha | sort)
Beyond Compare의 경우, 비교를 시작하고 완료 되기를 기다리 므로 bcomp
위 대신 (대신 bcompare
)에 사용해야합니다 . 을 사용하면 비교가 시작되고 명령 출력을 저장하기 위해 생성 된 임시 파일이 사라져 즉시 종료됩니다.bcomp
bcompare
자세한 내용은 여기를 참조하십시오 : http://zsh.sourceforge.net/Intro/intro_7.html
또한 이것을 주목하십시오 :
쉘은 임시 파일을 작성하고 명령이 완료되면이를 삭제합니다.
다음은 zsh가 지원하는 두 가지 유형의 프로세스 대체 (즉, # 2 및 # 3)의 차이점입니다.
zsh의 매뉴얼 페이지를 읽으면 <(...)이 = (...)와 비슷한 다른 형식의 프로세스 대체임을 알 수 있습니다. 둘 사이에는 중요한 차이점이 있습니다. <(...)의 경우, 쉘은 파일 대신 명명 된 파이프 (FIFO)를 작성합니다. 파일 시스템을 채우지 않기 때문에 더 좋습니다. 그러나 모든 경우에 작동하지는 않습니다. 실제로 위의 예에서 = (...)을 <(...)으로 바꾸면 fgrep -f <(...)를 제외하고는 모두 작동을 멈췄을 것입니다. 파이프를 편집하거나 메일 폴더로 열 수 없습니다. 그러나 fgrep은 파이프에서 단어 목록을 읽는 데 아무런 문제가 없습니다. foo | 이후 diff <(foo) 막대가 작동하지 않는 이유가 궁금 할 수 있습니다. diff-바 작동; diff가 인수 중 하나가-인 것을 발견하면 임시 파일을 작성하고 표준 입력을 임시 파일에 복사하기 때문입니다.
$(...)
프로세스 대체가 아니라 명령 대체입니다. <(...)
프로세스 대체입니다. 그것이 인용 된 구절이 전혀 언급되지 않은 이유 $(...)
입니다.
피쉬 쉘에서는 psub 로 파이프해야합니다 . Beyond Compare를 사용한 heroku 및 dokku 구성 비교의 예는 다음과 같습니다 .
bcompare (ssh me@myapp.pl dokku config myapp | sort | psub) (heroku config -a myapp | sort | psub)
meld
오픈 소스이며 Ubuntu 및 EPEL 리포지토리에서 사용할 수 있습니다. meldmerge.org
나는 종종 받아 들인 대답에 설명 된 기술을 사용합니다.
diff <(ls old) <(ls new)
그러나 나는 보통 위의 예보다 훨씬 더 복잡한 명령과 함께 사용한다는 것을 알았습니다. 이러한 경우 diff 명령을 작성하는 것은 성 가실 수 있습니다. 다른 사람들이 유용하게 사용할 수있는 몇 가지 솔루션을 생각해 냈습니다.
나는 diff를 실행하기 전에 관련 명령을 시도하는 시간의 99 %를 발견했습니다. 결과적으로 내가 diff하려는 명령이 내 역사에 있습니다 ... 왜 사용하지 않습니까?
마지막 두 명령을 실행하기 위해 기본 제공 수정 명령 (fc) bash를 사용합니다.
$ echo A
A
$ echo B
B
$ diff --color <( $(fc -ln -1 -1) ) <( $(fc -ln -2 -2 ) )
1c1
< B
---
> A
fc 플래그는 다음과 같습니다.
-n : 숫자가 없습니다. 나열 할 때 명령 번호를 표시하지 않습니다.
-l : Listing : 명령이 표준 출력에 나열됩니다.
는 -1
-1
히스토리에서 시작 및 종료 위치를 참조하며,이 경우 마지막 명령부터 마지막 명령까지만 발생합니다.
마지막으로 $()
서브 쉘에서 명령을 실행하기 위해 이것을 랩핑합니다 .
분명히 이것은 입력하기에 약간의 고통이므로 별칭을 만들 수 있습니다.
alias dl='diff --color <( $(fc -ln -1 -1) ) <( $(fc -ln -2 -2 ) )'
또는 함수를 생성 할 수 있습니다 :
dl() {
if [[ -z "$1" ]]; then
first="1"
else
first="$1"
fi
if [[ -z "$2" ]]; then
last="2"
else
last="$2"
fi
# shellcheck disable=SC2091
diff --color <( $(fc -ln "-$first" "-$first") ) <( $(fc -ln "-$last" "-$last") )
}
사용할 히스토리 라인 지정을 지원합니다. 둘 다 사용한 후 별칭이 내가 선호하는 버전이라는 것을 알았습니다.