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

Заменить все символические ссылки на оригинальные

У меня есть следующая структура каталогов

/symdir
  sym1 -> ../dir1
  sym2 -> ../dir2
  hello.txt

И затем

/dir1
  some
  files
  here
/dir2
  more
  files

Я хотел бы заменить символические ссылки в symdir (sym1, sym2) на оригиналы. То есть.

some_awesome_bash_func symdir symdir_output

Создал бы

/symdir_output
  /dir1
    some
    files
    here
  /dir2
    more
    files
  hello.txt

Как бы это сделать?

4b9b3361

Ответ 1

Вероятно, это не самый лучший способ, но он работает:

#!/bin/bash.exe

for link in $(find /symdir -type l)
do
  loc=$(dirname $link)
  dir=$(readlink $link)
  mv $dir $loc
  rm $link
done

Примечание. Это было написано на cygwin. Возможно, вам придется изменить #!.

Ответ 2

Мой личный трюк:

sed -i '' **/*

Обратите внимание, что я использую **, который использует параметр bash globstar, возможно, вам придется предварительно его включить:

shopt -s globstar

Ответ 3

Вы можете сделать это легко с помощью rsync:

rsync symdir/ symdir_output/ -a --copy-links -v

(- средство сохраняет в основном каждую деталь о файлах, -copy-links переопределяет -a, чтобы превратить символические ссылки в реальные файлы/каталоги, а -v - для подробностей)

Edit:

Извините, мое решение не делает именно то, что вы просили. Он сохранит имена символических ссылок вместо использования имен назначения. symdir_output будет иметь sym1 и sym2 вместо dir1 и dir2 (хотя sym1 и sym2 будут реальной копией dir1 и dir2). Надеюсь, он по-прежнему работает для вас.

Ответ 4

связанный ответ, это решение сохраняет файл в исходном месте и создает копию вместо символической ссылки

#/bin/bash

for f in $(find . -maxdepth 1 -type l)
do
    cp --remove-destination $(readlink -e $f) $f
done

Ответ 5

tl; dr: гораздо более общий, гораздо более надежный ответ:

find -type l -exec sh -c 'PREV=$(realpath -- "$1") && rm -- "$1" && cp -ar -- "$PREV" "$1"' resolver {} \;

Подход "rsync-to-other-destination" строго превосходит и обычно ведет к лучшему дизайну.

Ответ от @PinkFloyd не работает с необычными именами файлов, "хорошими" символическими ссылками или символическими каталогами. Я пришел сюда, потому что мне захотелось разрешить ссылки-symlinks, поэтому я ожидаю, что другие тоже найдут этот вопрос по этой причине. Кроме того, моя версия cp (GNU coreutils 8.25) неправильно обрабатывает --remove-destination для ответа @PinkFloyd для работы с каталогами. Поэтому в этом ответе используется ручная rm.

Также обратите внимание:

  • отсутствие -rf. Это потому, что символическая ссылка не является каталогом и не нуждается в -r. И если у вас нет символических ссылок с ограниченными разрешениями (зачем вам это нужно?!), вам также не нужно -f.
  • realpath отлично подходит в этом контексте, поскольку позволяет нам определить фактическое местоположение в текущей системе, в текущем контексте, и ничего больше не имеет значения. Этот путь не будет записан на диск, поэтому это не ошибка.
  • строка resolver предназначена для sh. См. man sh.
  • нужны двойные штрихи во всех случаях, если некоторая символьная ссылка называется --version или аналогичной.
  • из-за предоплаты-гарантии find ( "родительский каталог указан где-то перед его содержимым" ), это сначала заменит родительский каталог, а затем любые символические ссылки в символическом каталоге. Таким образом, это будет отлично работать с "уложенными" символическими ссылками.

Ответ 6

Я сделал это следующим образом:

ls -la | awk '/-\>/{system("rm "$10); system("cp "$12" .")}'

Как это работает:

ls -la выводит что-то вроде этого:

lrwxr-xr-x  1 username  groupname   44 10 Oct 12:17 Queue.swift -> ../../../Platform/DataStructures/Queue.swift

Столбец 10 - это Queue.swift, который является именем локального файла.
Столбец 12 ../../../Platform/DataStructures/Queue.swift, который является именем целевой ссылки

Первая часть команды awk равна '/-\>/', что означает "строки соответствия, содержащие -> с использованием регулярного выражения

Следующая часть команды awk - это два вызова system

Первый system("rm "$10), который расширяется до system("rm Queue.swift").
Это приведет к удалению исходного файла (символической ссылки)

Второй - system("cp "$12" ."), который расширяется до system("cp ../../../Platform/DataStructures/Queue.swift .")

Объединяя все вместе, что происходит для каждого файла (который является символической ссылкой), сначала мы удаляем символическую ссылку, затем копируем целевой файл в нее.


Хотя он не является частью исходного вопроса, я использовал его в сочетании с git. Если вы тоже это сделаете, вы можете запустить git status . после этого, и вы увидите кучу изменений типа (и ничего больше), например:

typechange: Queue.swift