Как получить полный путь к исходному файлу мягкой символической ссылки?

99

Я хочу scpфайл на сервер. Файл является символической ссылкой, и на самом деле я хочу скопировать исходный файл. В любом случае, я не хочу отслеживать путь к исходному файлу вручную, потому что его можно заменить. Если я могу получить абсолютный путь к исходному файлу, я могу sepс ним. Как я могу получить путь?

Eonil
источник
2
Большинство scpверсий по умолчанию используют символические ссылки, не так ли? Вы должны проверить свои и, возможно, сохранить себе работу.
jw013
@ jw103 Спасибо, что сообщили мне об этом. Я не знал :)
Eonil
2
Примечание: scp -rфорсирует следующие символические ссылки.
Эонил

Ответы:

129

Попробуйте эту строку:

readlink -f `which command`

Если commandв вашей $PATHпеременной, в противном случае вам нужно указать путь, который вы знаете.

маргаритка
источник
12
-fвернет путь к несуществующей конечной цели, пока существуют промежуточные цели ссылки ... Используйте, -eчтобы избежать этого, т.е. -eвернет ноль, если конечная цель не существует.
Peter.O
10
-fошибка readlink: illegal option -- fв OSX. Удаление это работало нормально.
Хит Границы
2
@HeathBorders Для OSX, если у вас установлена ​​домашняя версия coreutils, вы также можете использовать greadlinkвместо нее .
Адам Гент
23

В Linux readlinkчитает содержимое символической ссылки и readlink -fследует по символическим ссылкам на символические ссылки на символические ссылки и т. Д., Пока не найдет что-то, что не является символической ссылкой.

Это не обязательно для scp: scp всегда следует за символическими ссылками (он всегда копирует содержимое файла, игнорируя метаданные, за исключением того, что -pсохраняет время и режимы файлов, когда это возможно).

Если вы разочарованы тем, что метаданные scp могут и не могут сохранить, я предлагаю использовать rsync. Без опции rsync копирует содержимое файла, игнорируя метаданные. Обычно используемая опция -aсохраняет все метаданные, относящиеся к саду (время, символические ссылки, разрешения и владение), а также есть варианты для сохранения экзотических метаданных, таких как ACL и жесткие ссылки.

жилль
источник
readlink сделать только один шаг для чтения ссылок. например, в Ubuntu у нас есть / bin / zsh, который является символической ссылкой на / etc / alternatives / zsh, но это вторая символическая ссылка. Наконец, мы не получим реальный путь к файлу или каталогу. То же самое и с командой stat. Только readlink с опцией -f все решает.
Znik
9

Я использую команду ls, stat, readlink.

Взять файл /etc/localtimeв качестве примера

[flying@lempstacker ~]$ ls /etc/localtime 
/etc/localtime
[flying@lempstacker ~]$ ls -l /etc/localtime
lrwxrwxrwx. 1 root root 35 Aug  2 22:41 /etc/localtime -> ../usr/share/zoneinfo/Asia/Shanghai

операция

Использование статистики

[flying@lempstacker ~]$ stat /etc/localtime
  File: ‘/etc/localtime’ -> ‘../usr/share/zoneinfo/Asia/Shanghai’
  Size: 35          Blocks: 0          IO Block: 4096   symbolic link
Device: fd01h/64769d    Inode: 272202388   Links: 1
Access: (0777/lrwxrwxrwx)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2016-11-23 09:00:59.999887800 +0800
Modify: 2016-08-02 22:41:26.090389904 +0800
Change: 2016-08-02 22:41:26.090389904 +0800
 Birth: -
[flying@lempstacker ~]$ stat -c "%N" /etc/localtime
‘/etc/localtime’ -> ‘../usr/share/zoneinfo/Asia/Shanghai’

Использование readlink

[flying@lempstacker ~]$ readlink /etc/localtime
../usr/share/zoneinfo/Asia/Shanghai
[flying@lempstacker ~]$ readlink -f /etc/localtime
/usr/share/zoneinfo/Asia/Shanghai

Кажется, эта команда readlink -fлучше.

объяснение

-f, --canonicalize: канонизировать, рекурсивно следуя каждой символической ссылке в каждом компоненте данного имени; все, кроме последнего компонента должны существовать -man readlink

Горгона
источник
6

Стат предоставит вам эту информацию:

$ stat current
  File: `current' -> `/home/user/releases/build/'
  ...
многочлен
источник
readlink сделать только один шаг для чтения ссылок. например, в Ubuntu у нас есть / bin / zsh, который является символической ссылкой на / etc / alternatives / zsh, но это вторая символическая ссылка. Наконец, мы не получим реальный путь к файлу или каталогу. То же самое и с командой stat. Только readlink с опцией -f все решает.
Znik
5

Вы можете сделать

readlink -f `which command`

или вы можете получить что-то подобное в Linux с

stat `which command` | grep File

Если вы добавляете это в скрипт, проверьте ошибку. Если вы не хотите видеть сообщение об ошибке в том случае, если нет ссылки sym, перейдите к чему-то вроде

readlink -f "`which command`" 
Александр Сантос
источник
stat и realink без -f делают только один шаг. тогда лучше вызвать readlink -f.
Znik
3

Я бы использовал realpath <symlink>.

Вероятно, то, что вы называете «источником», является «целевым» файлом в соответствии с использованием ln:Usage: ln [OPTION]... [-T] TARGET LINK_NAME

XavierStuvw
источник
Спасибо Это сработало как шарм! с Mac OSX! где readlinkне резал ... тупой макинтош LOL
JayRizzo
0

readlink -f 'which java' не работает для меня

Но это сделал:

readlink -f $(which java)
NonCreature0714
источник
3
Не сработало, потому что это `не '.. но $()лучше практиковать в любом случае.
Стивен Раух
Почему понизить? Мой ответ является приемлемой альтернативой и, как говорится в комментарии, лучшей практикой.
NonCreature0714
1
Большинство людей, проголосовавших против, также не комментируют, поэтому просят объяснить, почему голосование за голосование редко дает вам объяснение, потому что голосующий против уже ушел и вряд ли вернется. Я бы посоветовал вам удалить опечатанный код, который не работает из вашего ответа. Я бы с удовольствием проголосовал, если бы вы нашли время, чтобы привести его в порядок и объяснить, почему $()лучше практиковаться.
Стивен Раух
Как объяснил вам Стивен, «не есть». Вы должны инкапсулировать command, но это не рекомендуется. лучше использовать $ (), потому что инкапсуляция $ ($ (команда)) намного проще и не требует специального экранирования. Тогда это предпочтительнее. В вашем первом примере вы использовали обычный апостроф, затем readlink пытается найти файл с именем «which java» с пробелом в его имени. Но вы намерены вызвать команду Java с аргументом java, чтобы найти двоичный исполняемый путь Java.
Znik
0

На MAC OX параметр -f не работает, readlink работает без каких-либо параметров.

KZs-MacBook-Pro:bin kz$ readlink -f pip3
readlink: illegal option -- f
usage: readlink [-n] [file ...]

KZs-MacBook-Pro:bin kz$ readlink pip3
../../../Library/Frameworks/Python.framework/Versions/3.7/bin/pip3
Xb74Dkjb
источник