Я столкнулся с той же проблемой, и я хотел бы предложить другое решение, основанное на tee
(, например решение @user4122451 ), но не создает временный файл, а также дает сбой, если sudo apt-get update
возвращает ненулевой код выхода, отличный от -, без вывода некоторой строки W:
, E:
или Err:
:
exec {fd}>&2 # copy stderr to some unused fd
bash -o pipefail -c "sudo apt-get update -y -q 2>&1 | tee /dev/fd/$fd | ( ! grep -q -e '^Err:' -e '^[WE]:' )"
result=$?
exec {fd}>&- # close file descriptor
В частности, это решение основано на параметреset -o pipefail
bash (, гарантирующем, что конвейер возвращает значение самой правой команды для выхода с ненулевым -статусом, в противном случае — нулевым )и использует дополнительный пронумерованный файл. дескриптор (см. также этот ответ SO).
Если вам не нужно делать параметр pipefail
локальным, вы можете просто написать:
set -o pipefail
exec {fd}>&2 # copy stderr to some unused fd
sudo apt-get update -y -q 2>&1 | tee /dev/fd/$fd | ( ! grep -q -e '^Err:' -e '^[WE]:' )
result=$?
exec {fd}>&- # close file descriptor
Один из способов сделать это - предварительно обработать один из наборов файлов. (В вашем вопросе говорится, что все файлы папки1 могут иметь abcd , а файлы папки2 могут иметь wxyz .
Например, find
может выполнять поиск файла внутри одного из деревьев, скажем folder1 , и передавать его в скрипт.
Внутри скрипта вы запускаете замену во входном файле и передаете результат в diff, который сравнивает его стандартный ввод с соответствующим файлом в другом дереве.
Я предполагаю, что у вас есть набор файлов на обоих деревьях, если это не так, вы можете добавить код для работы с ним (там также есть флаги в diff
, которые могут помочь ).
Минимальная версия будет выглядеть так (вы можете добавить несколько замен, например ). Обратите внимание, что вы также должны убедиться, что замещающий код делает то, что вам нужно, например, изменяет только слова, а не подстроки ).
find folder1 -type f -printf "%P\n" |
while read myfile
do
sed 's/abcd/wxyz/g' folder1/$myfile | diff -u folder2/$myfile -
done
Могут быть и более лаконичные способы, но этот ясно показывает места, где можно было бы добавить немного логики.