Я предполагал, что самый простой способ сравнить содержимое двух похожих каталогов - это что-то вроде
diff `ls old` `ls new`
Но я понимаю, почему это не работает; diff
передается большой длинный список файлов в командной строке, а не два потока, как я надеялся. Как мне передать два выхода в diff напрямую?
В Рыбной ракушке вы должны попасть в псаб . Вот пример сравнения конфигурации heroku и dokku с Beyond Compare :
bcompare (ssh me@myapp.pl dokku config myapp | sort | psub) (heroku config -a myapp | sort | psub)
Подстановка команд `…`
подставляет вывод команды в командную строку, поэтому diff
видит список файлов в обоих каталогах в качестве аргументов. Вам нужно, чтобы diff
увидел два имени файла в своей командной строке, а содержимое этих файлов должно быть списком каталогов. Вот что делает процесс замещения .
diff <(ls old) <(ls new)
Аргументы к diff
будут выглядеть как /dev/fd/3
и /dev/fd/4
: они являются файловыми дескрипторами, соответствующими двум каналам, созданным bash. Когда diff
откроет эти файлы, он будет подключен к стороне чтения каждого канала. Сторона записи каждого канала связана с командой ls
.
Для zsh использование =(command)
автоматически создает временный файл и заменяет =(command)
на путь к самому файлу. При подстановке команд $(command)
заменяется выходом команды .
Итак, есть три варианта:
$(...)
<(...)
=(...)
Подстановка процессов с добавлением zsh, # 3, очень полезна и может использоваться, например, для сравнения результатов двух команд с использованием инструмента сравнения, например, Beyond Compare:
bcomp =(ulimit -Sa | sort) =(ulimit -Ha | sort)
Для Beyond Compare обратите внимание, что вы должны использовать bcomp
для вышеупомянутого (вместо bcompare
), так как bcomp
запускает сравнение и ждет , чтобы оно завершилось. Если вы используете bcompare
, это запускает сравнение и сразу же завершается, из-за чего временные файлы, созданные для хранения вывода команд, исчезают.
Подробнее читайте здесь: http://zsh.sourceforge.net/Intro/intro_7.html
Также обратите внимание на это:
Обратите внимание, что shell создает временный файл и удаляет его после завершения команды.
и следующее, что является разницей между двумя типами подстановки Процессов, поддерживаемыми zsh (то есть # 2 и # 3):
Если вы читаете справочную страницу zsh, вы можете обратите внимание, что < (...) - это еще одна форма подстановки процесса, аналогичная = (...). Между ними есть важное различие. В случае < (...) оболочка создает именованный канал (FIFO) вместо файла. Это лучше, так как не заполняет файловую систему; но это не работает во всех случаях. Фактически, если бы мы заменили = (...) на < (...) в приведенных выше примерах, все они перестали бы работать, кроме fgrep -f < (...). Вы не можете редактировать канал или открывать его как почтовую папку; Однако у fgrep нет проблем с чтением списка слов из канала. Вы можете задаться вопросом, почему панель diff < (foo) не работает, так как foo | diff - барные работы; это связано с тем, что diff создает временный файл, если он замечает, что одним из его аргументов является -, а затем копирует свой стандартный ввод во временный файл.
Я часто использую технику, описанную в принятом ответе:
diff <(ls old) <(ls new)
, но я нахожу, что обычно использую его с намного более сложными командами, чем пример выше. В таких случаях это может быть раздражающим для обработки различной команды. Я предложил некоторые решения, которые другие могут найти полезным.
я нахожу, что 99% времени испытываю соответствующие команды прежде, чем работать различный. Следовательно, команды, которые я хочу к разности, находятся тут же в моей истории..., почему бы не использовать их?
я использую Команду Фиксации (ФК) удар, встроенный для выполнения последних двух команд:
$ echo A
A
$ echo B
B
$ diff --color <( $(fc -ln -1 -1) ) <( $(fc -ln -2 -2 ) )
1c1
< B
---
> A
флаги ФК:
-n: Никакое число. Это подавляет числа команды при списке.
-l: Список: команды перечислены на стандартном выводе.
-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") )
}
, который поддерживает определение строк истории для использования. После использования обоих я нахожу, что псевдоним является версией, которую я предпочитаю.