Скажем, у меня тоже есть программы a
и b
, которые я могу запускать с ./a
и ./b
.
Можно ли сравнивать их результаты без предварительной записи во временные файлы?
Скажем, у меня тоже есть программы a
и b
, которые я могу запускать с ./a
и ./b
.
Можно ли сравнивать их результаты без предварительной записи во временные файлы?
Используйте <(command)
для передачи вывода одной команды в другую программу, как если бы это было имя файла. Bash передает вывод программы в канал и передает имя файла, например /dev/fd/63
, внешней команде.
diff <(./a) <(./b)
Точно так же вы можете использовать >(command)
, если хотите передать что-то в команду.
На странице руководства Bash это называется «подстановкой процесса».
-bash: syntax error near unexpected token ('
. Я попробовал еще раз без скобок и получил -bash: java: No such file or directory
. Не работает, если у команды есть параметры?
- person styfle; 27.10.2011
alias diffcmd bash -c \'diff \<\(sh -c \!:1\) \<\( sh -c \!:2 \)\'
. (Тогда, например, diffcmd ls ls -a).
- person Paul Lynch; 15.05.2013
fseek
, zsh предлагает =(./a)
, который может использоваться идентично <(./a)
, но использует временный файл под капотом, который zsh удалит за вас.)
- person ssokolow; 24.01.2017
Добавляя к обоим ответам, если вы хотите увидеть параллельное сравнение, используйте vimdiff
:
vimdiff <(./a) <(./b)
Что-то вроде этого:
vimdiff
создает красивые, умные и интерактивные представления для сравнения различий. Похоже, что в большинстве систем он поставляется с пакетом vim
.
- person Tim Visée; 06.02.2017
vimdiff
также показывает не только отличающуюся строку, но и конкретный фрагмент текста, который отличается.
- person Anton Tarasenko; 27.11.2018
Один из вариантов - использовать именованные каналы (FIFO):
mkfifo a_fifo b_fifo
./a > a_fifo &
./b > b_fifo &
diff a_fifo b_fifo
... но решение Джона Кугельмана намного чище.
rm a_fifo b_fifo
.
- person Franklin Yu; 14.04.2016
Для всех, кому интересно, вот как вы выполняете замену процесса при использовании Fish shell:
Bash:
diff <(./a) <(./b)
Рыба:
diff (./a | psub) (./b | psub)
К сожалению, реализация в fish в настоящее время несовершенная; fish либо зависнет, либо будет использовать временный файл на диске. Вы также не можете использовать psub для вывода вашей команды.
Добавляем еще немного к и без того хорошим ответам (мне помогло!):
Команда docker
выводит свою справку в STD_ERR
(т.е. файловый дескриптор 2)
Я хотел посмотреть, дают ли docker attach
и docker attach --help
одинаковый результат
$ docker attach
$ docker attach --help
Просто набрав эти две команды, я сделал следующее:
$ diff <(!-2 2>&1) <(!! 2>&1)
!! то же самое, что! -1, что означает запуск команды 1 перед этой - последней командой
! -2 означает запуск команды за две до этой
2> & 1 означает отправку вывода file_descriptor 2 (STD_ERR) в то же место, что и вывод file_descriptor 1 (STD_OUT)
Надеюсь, это было полезно.
Для zsh использование =(command)
автоматически создает временный файл и заменяет =(command)
на путь к самому файлу. При обычной подстановке процесса $(command)
заменяется выводом команды.
Эта функция zsh очень полезна и может быть использована для сравнения вывода двух команд с помощью инструмента сравнения, например Beyond Compare:
bcomp =(ulimit -Sa | sort) =(ulimit -Ha | sort)
Для Beyond Compare обратите внимание, что вы должны использовать bcomp
для вышеуказанного (вместо bcompare
), поскольку bcomp
запускает сравнение и ожидает его завершения. Если вы используете bcompare
, это запускает сравнение и немедленно завершает работу, из-за чего временные файлы, созданные для хранения вывода команд, исчезают.
Подробнее читайте здесь: http://zsh.sourceforge.net/Intro/intro_7.html
Также обратите внимание на это:
Обратите внимание, что оболочка создает временный файл и удаляет его по завершении команды.
и следующее, в чем разница между $(...)
и =(...)
:
Если вы читаете справочную страницу zsh, вы можете заметить, что ‹(...) - это еще одна форма подстановки процесса, которая похожа на = (...). Между ними есть важное различие. В случае ‹(...) оболочка создает именованный канал (FIFO) вместо файла. Это лучше, так как это не заполняет файловую систему; но работает не во всех случаях. Фактически, если бы мы заменили = (...) на ‹(...) в приведенных выше примерах, все они перестали бы работать, кроме fgrep -f‹ (...). Вы не можете редактировать канал или открывать его как почтовую папку; Однако у fgrep нет проблем с чтением списка слов из канала. Вы можете спросить, почему diff ‹(foo) bar не работает, ведь foo | дифф - бар работает; это потому, что diff создает временный файл, если замечает, что один из его аргументов - -, а затем копирует свой стандартный ввод во временный файл.