Поскольку это cp
флагу недостает rsync:
-i, --interactive
prompt before overwrite (overrides a previous -n option)
Если временные метки последовательно формируются, их можно снять (например, с помощью sed) перед обработкой файлов любым другим методом, например
diff <(sed -E 's|[0-9]{2}:[0-9]{2}:[0-9]{2} [0-9]{2}/[0-9]{2}/[0-9]{2,4} [0-9]{1,} ||' fileA) <(sed -E 's|[0-9]{2}:[0-9]{2}:[0-9]{2} [0-9]{2}/[0-9]{2}/[0-9]{2,4} [0-9]{1,} ||' fileB)
Тестирование предоставленных Вами входных файлов:
$ diff \
<(sed -E 's|[0-9]{2}:[0-9]{2}:[0-9]{2} [0-9]{2}/[0-9]{2}/[0-9]{2,4} [0-9]{1,} ||' fileA) \
<(sed -E 's|[0-9]{2}:[0-9]{2}:[0-9]{2} [0-9]{2}/[0-9]{2}/[0-9]{2,4} [0-9]{1,} ||' fileB)
2,3c2,3
< abc xxx
< ghi eee ddd
---
> abc def
> ghi fff ddd
Самой простой командой для получения результата была бы следующая
$ diff <(tr -s "[0-9],:,/" " " < fileA) <(tr -s "[0-9],:,/" " " < < fileB)
Команда очень прямая и сложного регулярного выражения тоже нет.
Пример вывода будет такой же, как ниже
2,3c2,3
< abc xxx
< ghi eee ddd
---
> abc def
> ghi fff ddd
Надеюсь, это то, что вам нужно.
diff \
<(sed -r 's\[0-9]{2}:[0-9]{2}:[0-9]{2} [0-9]{2}/[0-9]{2}/[0-9]{4} [0-9]{6} \\' fileA) \
<(sed -r 's\[0-9]{2}:[0-9]{2}:[0-9]{2} [0-9]{2}/[0-9]{2}/[0-9]{4} [0-9]{6} \\' fileB) \
| egrep '^> ' | sed -r 's/^> //' > fileC
Пояснение
Удалите нерелевантные части, указанные в вопросе ОП, из файлов А и В и передайте их в diff.
diff выведет измененные разделы с предшествующим знаком «>», поэтому игнорируйте все остальное, кроме изменений.
Наконец, удалите начальный символ ">" из вывода и сохраните его в fileC в соответствии с вопросом.
Изначально я сделал это немного по-другому, но я просто заметил, что файлы могут отличаться в несоответствующем разделе, поэтому его нужно предварительно удалить, а не пост-разделить, иначе diff будет выводить информацию, которая на самом деле не изменилась при рассмотрении соответствующих частей. Только.
В примере ввода cat fileC
дает:
abc def
ghi fff ddd
Команда sed ищет предоставленное регулярное выражение, которое описывает нерелевантные данные, и заменяет это пустой строкой, т. Е. Удаляет ее. .
{ paste -d\| /dev/fd/3 /dev/fd/4 |
sed '/\([^ ]*\) [0-9:/ ]*\(.*\)|\1 .*\2/d;=' |
sed 'N;s/\(\n\)\(.*\)|/:\tFILEA: \2\1\tFILEB: /'
} 3<<\FILEA 4<<\FILEB
qaqa rara
abc 10:12:25 08/20/2014 123456 def
ghi fff ddd
jkl 09:20:40 08/20/2014 978645 dfdf gggg
FILEA
qaqa rara
abc 10:32:15 07/15/2014 121456 xxx
ghi eee ddd
jkl 10:01:22 07/15/2014 971645 dfdf gggg
FILEB
2: FILEA: abc 10:12:25 08/20/2014 123456 def
FILEB: abc 10:32:15 07/15/2014 121456 xxx
3: FILEA: ghi fff ddd
FILEB: ghi eee ddd
Не нужно избавляться от времени и даты - они не представляют большого препятствия, если символы, их составляющие, надежны.
В указанном выше конвейере paste
сначала добавляет соответствующую строку из FILEB
в конец каждой из строк FILEA
с одним | Затем разделитель
распечатывает результаты в стандартный вывод
.
sed
выбирает поток и сравнивает:
первую последовательность из 0 или более символов, которые не являются пробелами (обозначено как \ 1
)
все символы, которые встречаются между следующими последовательностями: (обозначается как \ 2
)
хотя бы один символ <пробел>
, затем 0 или более из любого из следующих значений:
символов
символов
<: двоеточие>
символов
символов
до последнего, но не включая его встречающийся символ |
в строке
... с | \ 1. * \ 2
. Если они совпадают, sed
удаляет строку. В противном случае он печатает строку, которой предшествует ее номер.
Последний процесс sed
просто улучшает вывод (надеюсь) .