Вопрос или проблема
У меня есть эта папка /full/path/sourceFolder
с следующими файлами:
full/path/sourceFolder/fileA
/full/path/sourceFolder/copyA -> fileA
/full/path/sourceFolder/copyB
Вы можете видеть, что символическая ссылка указывает на файл в той же папке и не использует полный путь, а полагается на относительный путь для создания ссылки.
Теперь мне нужна команда копирования, которая скопирует все файлы с именем copy* из sourceFolder в destinationFolder. Когда я копирую файл copyA, он должен скопировать источник символической ссылки, т.е. fileA, но сохранить имя copyA. Команда копирования также должна работать для копирования файла copyB.
Можно ли это сделать?
Я пробовал эти команды, но они не работают, в основном потому, что моя ссылка является относительной:
cp -rf --preserve=links /full/path/sourceFolder/copy* /target/path/
cp -RP /full/path/sourceFolder/copy* /target/path/
cp -Hrf /full/path/sourceFolder/copy* /target/path/
cp -Lrf /full/path/sourceFolder/copy* /target/path/
У меня заканчиваются идеи, Какой самый элегантный способ этого достичь?
Следующая команда скопирует исходный файл с символической ссылкой, но не скопирует ссылочный файл.
cp -d /full/path/sourceFolder/copy* /target/path/
Следующая команда скопирует и ссылочный файл тоже
cp -d /full/path/sourceFolder/file* /target/path/
Опция -d является сокращением для –no-dereference –preserve=links
Ответ или решение
Как скопировать символические ссылки с относительными путями в Unix
Скопировать символические ссылки с относительными путями в Unix может быть непростой задачей, особенно когда вам нужно сохранить структуру имен файлов и ссылки. Давайте разберем, как это можно сделать, с учетом всех нюансов.
Исходные данные
Предположим, у вас есть следующая структура файлов в каталоге /full/path/sourceFolder
:
/full/path/sourceFolder/fileA
/full/path/sourceFolder/copyA -> fileA
/full/path/sourceFolder/copyB
Вы хотите скопировать все файлы, начинающиеся с copy
, в целевой каталог /target/path/
, и при этом обеспечить, чтобы при копировании copyA
сохранялась ссылка на fileA
, а сам файл copyB
был скопирован как есть.
Проблема
Некоторые подходы, такие как использование опций -r
, -P
, -L
, и -H
, могут не сработать так, как вы ожидаете, из-за различий в трактовке символических ссылок и их запоминания относительных путей. Поэтому, давайте рассмотрим несколько вариантов, как можно решить эту задачу более изящно и эффективно.
Решение
-
Копирование символической ссылки как есть
Если вы хотите, чтобы символическая ссылка
copyA
указывала на оригинал (fileA
), вам нужно использовать опцию-d
или--no-dereference
. Эта опция позволяет копировать символическую ссылку без разыменования (т. е. без копирования файла, на который указывает ссылка):cp -d /full/path/sourceFolder/copy* /target/path/
В результате команда создаст символическую ссылку
copyA
в целевом каталоге, которая будет по-прежнему указывать наfileA
. -
Копирование файла по ссылке
Если вы хотите, чтобы
copyA
копировался какfileA
, аcopyB
как обычный файл, вам потребуется сначала разыменовать символические ссылки для файла, на который они указывают. Однако, это можно сделать следующим образом:Используйте следующую последовательность команд:
for link in /full/path/sourceFolder/copy*; do file=$(readlink "$link") if [ "$file" ]; then # Если это ссылка, копируем файл cp "$file" /target/path/ else # Если это обычный файл, просто копируем его cp "$link" /target/path/ fi done
В этом скрипте:
- Мы перебираем все файлы с префиксом
copy
. - Используем
readlink
для получения целевого файла символической ссылки. - Копируем либо файл, на который ссылается ссылка, либо сам файл.
- Мы перебираем все файлы с префиксом
Заключение
Этот подход позволяет вам контролировать процесс копирования и обеспечивать правильное поведение для символических ссылок и обычных файлов, сохраняя при этом относительные пути. Вы можете адаптировать этот скрипт под свои нужды, добавляя дополнительные проверки и настройки.
Таким образом, описанные методы помогут вам справиться с задачей копирования символических ссылок с сохранением имен файлов и их относительных путей в Unix-системах.