Это особенность патча GNU .Поскольку вы не указали конкретный файл для исправления, он должен быть как-то выведен из входных данных.По сути, если вы не указываете пути (только базовые имена), предполагается, что он должен пропатчить файл с более коротким именем, если только не передан --posix
аргумент командной строки или не установлена POSIXLY_CORRECT
переменная окружения:
patch --posix <p
# or
POSIXLY_CORRECT=1 patch <p
В вашем случае, между a
и b
первый выбран правильно, но для ab
и b
второй выбран в качестве цели патча (как указывает строка patching file b
), но исправление не выполняется, поэтому возникает ошибка.
Вы также можете исправить это поведение, указав цель исправления явно:
patch ab <p
Копание в документах
В патче GNU используетсяследующая логика (см. руководство по исправлению, раздел «10.6 Несколько исправлений в файле» ):
Сначала исправление принимает упорядоченный список имен файлов-кандидатов следующим образом:
- Если заголовок совпадает с контентом diff, patch берет старые и новые имена файлов в заголовке....
...
Затем исправление выбирает имя файла из списка кандидатов следующим образом:
- Если существуют некоторые из названных файловpatch выбирает первое имя, если оно соответствует POSIX, и лучшее имя в противном случае.
Для " единый контекстный формат " "старый" файл упоминается после ---
(a
или ab
в вашем случае), а также«новый» файл упоминается после +++
(b
в вашем случае).
Если оба файла существуют и patch
не настроен на «подтверждение POSIX» (например, установкой POSIXLY_CORRECT
переменная окружения или --posix
аргумент командной строки, см. «10.12 patch и раздел POSIX Standard» руководства ), тогда patch
выберет «лучшее» имя из двух.«Имя» здесь включает полный путь, полученный из файла патча (в вашем случае это не имеет значения).Подробности уточняются позже:
Чтобы определить лучший из непустого списка имен файлов, patch сначала берет все имена с наименьшим количеством компонентов пути;из них он берет все имена с самым коротким базовым именем;из них он принимает все самые короткие имена;наконец, оно занимает первое оставшееся имя.
«Компонент имени» - это, в основном, имя папки / файла (например, /foo/bar/baz
имеет три из них), «базовое имя» - это просто имяфайл (baz
).Итак, если имена a
(старые) и b
(новые) и оба файла существуют, «лучшего имени» не существует, поэтому первый из них исправляется.Но если имена ab
(старые) и b
(новые) и оба файла существуют, то b
«лучше», поэтому инструмент пытается его исправить и не удается.
У меня нетИдея, почему это поведение было сделано по умолчанию.