How to copy symbolic links?
Personally, I use cp -av for most of my heavy copying. That way, I can preserve everything — even recursively — and see the output. Of course, that is just personal preference.
As to why your other options did not do what you expected, -s makes a link instead of copying and -L follows the links in the source to find the file to copy instead of copying the links themselves.
+1 for the -a option. Heh, I’ve looked up options in cp ‘s manpage countless times, yet I must have always skimmed over this one. I have until now been using -dpr , but -a covers all of those, plus the preservation of a couple of other attributes. If I’d have needed these other attributes I would have probably looked up the —preserve option again and used -dr —preserve=all , which is exactly what -a is! Well at least I know now – -a is perfect and this is what I’ll be using from now on.
This didn’t work on Cygwin. —preserve=links wasn’t enough. It still said cp: omitting directory . But -av worked.
Just as the man page says, use -P . This setting says:
-P, --no-dereference never follow symbolic links in SOURCE
Thanks, I’ve seen and benefited from your answer 3 times now different times over a year. Can’t seem to remember it!
This works, but my man page say «-P never follow symbolic links in SOURCE», which is not intuitively the same as «copy symlinks as symlinks to destination». («never follow» makes it sound like it works in combination with -R)
-a same as -dR --preserve=all -R copy directories recursively -d same as --no-dereference --preserve=links --no-dereference never follow symbolic links in SOURCE
If the links contain relative paths, then, copying the link will not adjust the relative path. Use readlink , with the switch -f to follow recursively, in order to get the absolute path of the link. For example:
ln -s $(readlink -f old/dir/oldlink) new/dir/newlink
If preserving the relative paths is what you want, than the option -P of cp , as said by Ignacio Vazquez-Abrams, is what you need.
It may be a bad idea to dereference recursively if all you are trying to do is to convert symlinks from being relative to absolute. The recursion is not needed here, and sometimes chained symlinks are there for a reason. Symlinks are often used to specify choices or configuration options. For example, on my system there is a symlink chain /usr/share/dict/words -> /etc/dictionaries-common/words -> /usr/share/dict/british-english which specifies the preferred dictionary. If you were to recursively dereference this chain, the resulting symlink would ignore any future changes to this preference.
You may very well not want to modify a relative path. I have cases where there are different versions of a file (that is multiple files with different names), and a symbolic link to the latest version, and all stored in the same directory. Copying the whole directory I want the link unchanged so it still points to the file in its new location.
True, but the OP question explicitely says: > The resulting links should be independent from their prototypes and lead directly to their target objects.
Most of the time, when I need to copy many symbolic links, I’m actually trying to mirror a directory tree. So I want the symlinks and everything else.
This is overkill for copying just a few symlinks, but if you’re actually trying to copy an entire tree, this can be very useful:
user@host:/cwd$ ( cd /path/to/src ; tar cf - . ) | ( cd /path/to/dest ; tar xf - )
tar doesn’t resolve the symlink by default, so symlinks in the mirror copy will point to the same locations as those in the original tree.
This trick makes use of subshells to get the tar command into position at the root of the directory to be mirrored; you can leave one of them out (along with the associated cd command) if you’re already in the src or dest directories:
# already in src? user@host:/src$ tar cf - . | ( cd /path/to/dest ; tar xf - ) # already in dest? user@host:/dest$ ( cd /path/to/src ; tar cf - . ) | tar xf - # just need src/foo? # this result will be a mirror copy at dest/foo user@host:/src$ tar cf - foo | ( cd /path/to/dest ; tar xf - ) # mirror to another system? user@host:/src$ tar cf - . | ssh user@example.com '( cd /path/to/dest ; tar xf - )'
Again, this isn’t appropriate for every time you want to copy symbolic links, but it is a very useful snippet to know.
Символические и жесткие ссылки Linux
Символические и жесткие ссылки — это особенность файловой системы Linux, которая позволяет размещать один и тот же файл в нескольких директориях. Это очень похоже на ярлыки в Windows, так как файл на самом деле остается там же где и был, но вы можете на него сослаться из любого другого места.
В Linux существует два типа ссылок на файлы. Это символические и жесткие ссылки Linux. Они очень сильно отличаются и каждый тип имеет очень важное значение. В этой небольшой статье мы рассмотрим чем же отличаются эти ссылки, зачем они нужны, а также как создавать ссылки на файлы в Linux.
Символические ссылки
Символические ссылки более всего похожи на обычные ярлыки. Они содержат адрес нужного файла в вашей файловой системе. Когда вы пытаетесь открыть такую ссылку, то открывается целевой файл или папка. Главное ее отличие от жестких ссылок в том, что при удалении целевого файла ссылка останется, но она будет указывать в никуда, поскольку файла на самом деле больше нет.
Вот основные особенности символических ссылок:
- Могут ссылаться на файлы и каталоги;
- После удаления, перемещения или переименования файла становятся недействительными;
- Права доступа и номер inode отличаются от исходного файла;
- При изменении прав доступа для исходного файла, права на ссылку останутся неизменными;
- Можно ссылаться на другие разделы диска;
- Содержат только имя файла, а не его содержимое.
Теперь давайте рассмотрим жесткие ссылки.
Жесткие ссылки
Этот тип ссылок реализован на более низком уровне файловой системы. Файл размещен только в определенном месте жесткого диска. Но на это место могут ссылаться несколько ссылок из файловой системы. Каждая из ссылок — это отдельный файл, но ведут они к одному участку жесткого диска. Файл можно перемещать между каталогами, и все ссылки останутся рабочими, поскольку для них неважно имя. Рассмотрим особенности:
- Работают только в пределах одной файловой системы;
- Нельзя ссылаться на каталоги;
- Имеют ту же информацию inode и набор разрешений что и у исходного файла;
- Разрешения на ссылку изменяться при изменении разрешений файла;
- Можно перемещать и переименовывать и даже удалять файл без вреда ссылке.
Использование ссылок в Linux
Теоретические отличия вы знаете, но осталось закрепить все это на практике, поэтому давайте приведем несколько примеров работы со ссылками в Linux. Для создания символических ссылок существует утилита ln. Ее синтаксис очень прост:
$ ln опции файл_источник файл_ссылки
- -d — разрешить создавать жесткие ссылки для директорий суперпользователю;
- -f — удалять существующие ссылки;
- -i — спрашивать нужно ли удалять существующие ссылки;
- -P — создать жесткую ссылку;
- -r — создать символическую ссылку с относительным путем к файлу;
- -s — создать символическую ссылку.
Создание символических ссылок
Сначала создайте папку test и перейдите в нее:
Затем создайте файл с именем source с каким-либо текстом:
echo «текст текст текст текст» > source
$ cat source
Файл готов, дальше создадим символическую ссылку Linux, для этого используется команда ln с опцией -s:
Попробуем посмотреть содержимое файла по ссылке:
Как видите, нет никакой разницы между ней и исходным файлом. Но утилита ls покажет что это действительно ссылка:
Несмотря на то, что содержимое одинаковое, здесь мы видим, что адрес иноды и права доступа к файлам отличаются, кроме того, явно показано что это символическая ссылка Linux.
Теперь удалите исходный файл и посмотрите что будет:
Вы получите ошибку, что такого файла не существует, потому что мы действительно удалили исходный файл. Если вы удалите ссылку, то исходный файл останется на месте.
Создание жестких ссылок
Снова создайте файл source с произвольным текстом:
echo «текст текст текст текст» > source
$ cat source
Теперь создадим жесткую ссылку Linux. Для этого достаточно вызвать утилиту без параметров:
Посмотрите содержимое файла:
Данные те же самые, а если мы посмотрим вывод утилиты ls, то увидим что inode и права доступа тоже совпадают:
Если для одного из файлов поменять разрешения, то они изменяться и у другого. Теперь удалите исходный файл:
Затем посмотрите содержимое:
Как видите, ничего не произошло и ссылка по-прежнему указывает на нужный участок диска, это главное отличие жесткой ссылки от символической. Мы можем сделать вывод, что жесткая ссылка linux это обычный файл. Каждый файл имеет как минимум одну ссылку, но для некоторых мы можем создать несколько ссылок.
Выводы
Это все, что вам было необходимо знать про символические и жесткие ссылки linux. Надеюсь, вы получили общее представление об этих возможностях файловой системы и сможете использовать их для решения своих задач.
На завершение видео про ссылки в Linux:
Обнаружили ошибку в тексте? Сообщите мне об этом. Выделите текст с ошибкой и нажмите Ctrl+Enter.
Как скопировать символические ссылки?
Лично я использую cp -av для большей части моего тяжелого копирования. Таким образом, я могу сохранить все — даже рекурсивно — и посмотреть результат. Конечно, это просто личное предпочтение.
Что касается того, почему другие ваши варианты не дали ожидаемого результата, -s вместо ссылки копирует ссылку, а -L следует по ссылкам в источнике, чтобы найти файл для копирования, а не копировать сами ссылки.
Как написано в справочной странице, используйте -P .
Если ссылки содержат относительные пути, то копирование ссылки не будет корректировать относительный путь. Используйте readlink , с ключом -f чтобы следовать рекурсивно, чтобы получить абсолютный путь ссылки. Например:
ln -s $(readlink -f old/dir/oldlink) new/dir/newlink
Если вы хотите сохранить относительные пути, тогда вам нужна опция -P для cp , как сказал Игнасио Васкес-Абрамс.
Как некоторые прокомментировали:
-a same as -dR --preserve=all -R copy directories recursively -d same as --no-dereference --preserve=links --no-dereference never follow symbolic links in SOURCE
Я использовал следующее, чтобы дублировать действительно большой каталог. Все символические ссылки были сохранены, копия была сделана рекурсивно, и я смог получить некоторую визуальную обратную связь с процессом:
cp -Prv /sourcer_dir/* /target_dir
В большинстве случаев, когда мне нужно скопировать много символических ссылок, я на самом деле пытаюсь отразить дерево каталогов. Поэтому я хочу символические ссылки и все остальное.
Это избыточно для копирования всего нескольких символических ссылок, но если вы на самом деле пытаетесь скопировать целое дерево, это может быть очень полезно:
Используйте смолу.
user@host:/cwd$ ( cd /path/to/src ; tar cf - . ) | ( cd /path/to/dest ; tar xf - )
tar не разрешает символическую ссылку по умолчанию, поэтому символические ссылки в зеркальной копии будут указывать на те же места, что и в исходном дереве.
Этот трюк использует подоболочки, чтобы получить команду tar в корне каталога, который нужно отразить; Вы можете оставить один из них (вместе со связанной командой cd ), если вы уже находитесь в каталогах src или dest :
# already in src? user@host:/src$ tar cf - . | ( cd /path/to/dest ; tar xf - ) # already in dest? user@host:/dest$ ( cd /path/to/src ; tar cf - . ) | tar xf - # just need src/foo? # this result will be a mirror copy at dest/foo user@host:/src$ tar cf - foo | ( cd /path/to/dest ; tar xf - ) # mirror to another system? user@host:/src$ tar cf - . | ssh user@example.com '( cd /path/to/dest ; tar xf - )'
Опять же, это не подходит для каждого случая, когда вы хотите скопировать символические ссылки, но это очень полезный фрагмент кода.