Подтвердить что ты не робот

Как преобразовать символическую ссылку в обычный файл?

Каков самый прямой способ преобразования символической ссылки в обычный файл (т.е. копия цели символической ссылки)?

Предположим, что filename является символической ссылкой на target. Очевидная процедура превращения его в копию:

cp filename filename-backup
rm filename
mv filename-backup filename

Есть ли более прямой способ (т.е. одна команда)?

4b9b3361

Ответ 1

Нет единой команды для преобразования символической ссылки в обычный файл. Самый прямой способ - использовать readlink, чтобы найти файл, на который указывает символическая ссылка, а затем скопировать этот файл через символическую ссылку:

cp --remove-destination `readlink bar.pdf` bar.pdf

Конечно, если bar.pdf является, на самом деле, обычным файлом для начала, тогда это скроет файл. Поэтому было бы целесообразно провести проверку правильности.

Ответ 2

Просто перефразируйте другие ответы, но добавив "проверку работоспособности", чтобы убедиться, что связанная ссылка на самом деле является символической ссылкой:

removelink() {
  [ -L "$1" ] && cp --remove-destination "$(readlink "$1")" "$1"
}

Это говорит о том, что если файл является символической ссылкой, запустите команду копирования.

Ответ 3

for f in $(find -type l);do cp --remove-destination $(readlink $f) $f;done;
  • Проверить символические ссылки в текущем каталоге и подкаталогах find -type l
  • Получить связанный путь к файлу readlink $f
  • Удалить символическую ссылку и скопировать файл cp --remove-destination $(readlink $f) $f

Ответ 4

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

Просто выполните встроенный sed без преобразований:

sed -i ';' /path/to/symbolic/link

Ответ 5

В OSX

rsync `readlink bar.pdf` bar.pdf

Ответ 6

Нет необходимости в каких-либо смешных сценариях оболочки, rsync или специальных опциях GNU на cp. Достаточно просто:

$ mv target link

Если мы не знаем цель, подставим выражение $(readlink link) для target выше:

$ mv $(readlink link) link

Утилита mv соответствует системному вызову rename для POSIX-подобных систем (по крайней мере, если не работает в разных томах файловой системы). Системный вызов rename удаляет целевой объект, если он существует, за одну операцию.

Мы можем просто mv указать целевой файл в символическую ссылку:

$ touch target
$ ln -sf target link
$ ls -l target link
lrwxrwxrwx 1 kaz kaz 6 Sep  7  2016 link -> target
-rw-rw-r-- 1 kaz kaz 0 Sep  7  2016 target
$ mv target link
$ ls -l target link
ls: cannot access target: No such file or directory
-rw-rw-r-- 1 kaz kaz 0 Sep  7  2016 link

Если мы делаем это через тома, оно моделируется. GNU Coreutils mv сначала пытается выполнить системный вызов rename. Когда это не удается, он использует unlink для удаления символической ссылки назначения и выполняет копию:

$ touch /tmp/target
$ ln -sf /tmp/target link
$ ls -l /tmp/target link
lrwxrwxrwx 1 kaz kaz 11 Sep  7  2016 link -> /tmp/target
-rw-rw-r-- 1 kaz kaz  0 Sep  7 16:20 /tmp/target
$ strace mv /tmp/target link
[ ... snip ... ]
stat("link", {st_mode=S_IFREG|0664, st_size=0, ...}) = 0
lstat("/tmp/target", {st_mode=S_IFREG|0664, st_size=0, ...}) = 0
lstat("link", {st_mode=S_IFLNK|0777, st_size=11, ...}) = 0
rename("/tmp/target", "link")           = -1 EXDEV (Invalid cross-device link)
unlink("link")                          = 0
open("/tmp/target", O_RDONLY|O_NOFOLLOW) = 3
fstat(3, {st_mode=S_IFREG|0664, st_size=0, ...}) = 0
open("link", O_WRONLY|O_CREAT|O_EXCL, 0600) = 4
fstat(4, {st_mode=S_IFREG|0600, st_size=0, ...}) = 0
fadvise64(3, 0, 0, POSIX_FADV_SEQUENTIAL) = 0
read(3, "", 65536)                      = 0
[ ... ]
close(0)                                = 0
close(1)                                = 0
exit_group(0)                           = ?
+++ exited with 0 +++
$ ls -l /tmp/target link
ls: cannot access /tmp/target: No such file or directory
-rw-rw-r-- 1 kaz kaz 0 Sep  7 16:20 link

Ответ 7

cp может удалить целевой файл:

cp --remove-destination target filename

Ответ 8

Многие уже заявили следующее решение:

cp --remove-destination `readlink file` file

Однако это не будет работать с символически связанными каталогами.

Добавление рекурсивной и силы не будет работать:

cp -rf --remove-destination `readlink file` file

cp: невозможно скопировать каталог, путь/файл в себя, файл

Поэтому, вероятно, более безопасно сначала удалить символическую ссылку:

resolve-symbolic-link() {
  if [ -L $1 ]; then
      temp="$(readlink "$1")";
      rm -rf "$1";
      cp -rf "$temp" "$1";
  fi
}

Не совсем один лайнер, как вы надеялись, но поместите его в оболочку, и это может быть.

Ответ 9

Это отлично сработало для меня (отредактировано для работы с пробелами):

find . -type l | while read f; do /bin/cp -rf --remove-destination -f $(find . -name $(readlink "${f}")) "${f}";done;

Позволяет рекурсивно преобразовывать все символические ссылки под текущей рабочей папкой в ​​свой обычный файл. Также не просит вас перезаписать. "/bin/cp" существует, чтобы вы могли обойти возможный псевдоним cp -i на вашей ОС, который предотвращает работу "-rf".

Ответ 10

Нет единой команды. Но если вам не нужна копия, и все, что вам нужно, это еще одна ссылка, вы можете заменить символическую ссылку ссылкой (иначе говоря, "жесткой ссылкой" ). Это работает только в том случае, если они находятся в одном разделе, BTW.

rm filename
ln target filename

Ответ 11

Rsync может нейтрально использовать символическую ссылку для вас, используя флаг -L.

[[email protected] ~]$ rsync -h | grep -- -L
 -L, --copy-links            transform symlink into referent file/dir

Было бы просто: rsync -L <symlink> <destination>

Ответ 12

в случае "относительных" символических ссылок вы можете добавить оператор awk в ответ @jared:

for f in $(find . -type l); do /bin/cp -rf --remove-destination -f $(find . \! -type l -name $(readlink $f | awk -F"../" '{print $NF}')) $f;done;

Если у вас есть символические ссылки, указывающие на каталоги, вам нужно использовать более радикальный подход, потому что cp --remove-destination не работает вместе с каталогами симлинк правильно

for f in `find . -type l`; do (cd `dirname $f`; target=`basename $f`; source=`readlink $target` ; rm -rf $target && cp -r $source $target); done

Конечно, это может быть написано с меньшими затратами. но, на мой взгляд, неплохо читать.

Ответ 13

Это решение работает с файлами symlink и папками/подпапками symlink.

Требуется одна строка, не требуется script. Это было бы идеально для экспорта или передачи символических ссылок в другом месте.

Поместите все в папку.

rsync --archive --copy-links --recursive folderContainingSymlinkFilesAndSymlinkFoldersAndSubfolders myNewFolder

Ответ 14

Другой подход, если вы часто это делаете, - это адаптировать ответ kbrock в оболочку script и поместить его в /usr/bin/. Что-то вроде:

if [ $# -ne 1 ] 
then
  echo "Usage: $0 filename"
  exit 1
fi
[ -L "$1" ] && cp --remove-destination "$(readlink "$1")" "$1"

chmod + x it, а затем просто запустите его как обычную команду.