Я могу воспроизвести приведенные выше сообщения следующим образом:
mkdir test; cd test
mkdir repos; cd repos
mkdir g; cd g
git init
touch a
git add a
git commit -m test
cd ..
git clone g h
cd ..
mkdir copy
cp -ua repos copy
cp -uav repos copy
Запуск команды cp -ua
под strace
покажет, что она действительно удаляет (unlink
) файлы, которые он говорит.
Случилось так, что объекты в repo/h/.git/objects
являются жесткими ссылками на объекты в repo/g/.git/objects
. (В моем исходном случае я копировал репозиторий, содержащий вложенные репозитории, которые изначально были созданы как клоны основного репо).
cp -a
означает cp --preserve
, что задокументировано как
--preserve[=ATTR_LIST]
сохранить указанные атрибуты (по умолчанию: режим, владение, временные метки ), по возможности дополнительные атрибуты: контекст, ссылки, xattr, все
Развязка происходит как часть сохранения жестких ссылок:
linkat(AT_FDCWD, "копировать/repos/g/.git/objects/2b/bf350cea1fb4fd036235d7e6c36eb600e68885", AT_FDCWD, "копия/репозитории/h/.git/objects/2b/bf350cea1fb4fd036235d7e6c36eb600e68885", 0) = -1 EEXIST (Файл существует)
unlink("copy/repos/h/.git/объекты/2b/bf350cea1fb4fd036235d7e6c36eb600e68885") = 0
linkat(AT_FDCWD, "копировать/repos/g/.git/objects/2b/bf350cea1fb4fd036235d7e6c36eb600e68885", AT_FDCWD, "копия/репозитории/h/.git/objects/2b/bf350cea1fb4fd036235d7e6c36eb600e68885", 0) = 0
А почему именно он генерирует сообщения, которые меня так смутили?
Похоже, -u
(--update
) не совсем реализовано в этом коде. В основном это оптимизация производительности, позволяющая избежать ненужного повторного копирования данных. Создание жестких ссылок не требует копирования каких-либо данных.
В документации мы можем увидеть другие сценарии, в которых cp
также должен удалять файлы:
-f, --force если существующий файл назначения не может быть открыт, удалите его и повторите попытку (этот параметр игнорируется, если также используется параметр -n)
В случае с -f
я понимаю, что он может захотеть показать определенные файлы, которые он должен «форсировать».
Я полагаю, было бы также полезно показать удаление, если cp
прерывается. В противном случае пользователи вряд ли поймут, что файл мог быть удален из места назначения (в качестве промежуточного шага).
Главный вопрос заключается в том, почему он также не показывал сообщение при повторном создании ссылок, что было бы менее запутанным. Я подозреваю, что это особенность опции -u
.
Команда zgrep
работает с файлами .tar.gz без извлечения содержимого.
Предположим, что под «без извлечения» вы подразумеваете «без сохранения извлеченных файлов на диск» :
for file in *.tar.gz ; do
tar xzOf $file b | grep --label=$file/b -H foo
done
параметры tar:
x
извлекать
z
gunzip перед извлечением
O
дампа в стандартный вывод вместо создания файла (заглавная буква ой, а не цифра ноль)
f
из указанного файла tar
Параметры grep (предложены JJoao)
- label = ...
использовать указанную метку в качестве имени файла
-H
печатать имя файла для каждого совпадение