Конвертировать символические ссылки в жесткие ссылки

25

Я хотел бы рекурсивно преобразовывать мягкие ссылки в жесткие ссылки в каталоге. Я пробовал что-то вроде этого:

for f in *; do (mv $f{,~} && ln $(readlink $f~) && rm $f~) done

... но у него есть две основные проблемы:

  • не рекурсивный
  • подбирает файлы, которые не являются символическими ссылками

Было бы неплохо как-то прокормить вышеприведенную строку find -type l, но я не уверен, как это сделать.

Аттила О.
источник
1
Смотрите также [это обсуждение] [1] ( cp -aH). [1]: unix.stackexchange.com/questions/94185/…
Михаил Шигорин,

Ответы:

34

Эта команда должна работать:

find -type l -exec bash -c 'ln -f "$(readlink -m "$0")" "$0"' {} \;

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

  • find -type l находит все ссылки в текущем каталоге.

  • -exec bash -c '...' {} \;вызывает bash для выполнения ....

    Он передает {}- имя ссылки, которая в данный момент обрабатывается - как аргумент, к которому bash может получить доступ как $0.

  • readlink -m "$0" возвращает абсолютный путь к месту назначения символической ссылки.

  • ln -f "$(readlink -m "$0")" "$0"перезаписывает ( -f) символическую ссылку $0жесткой ссылкой на свою цель.

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

Деннис
источник
Что касается последнего абзаца, не будет ли достаточно указать абсолютные пути к bashи ln?
Даниэль Бек
2
Моя проблема заключалась в том, что readlink возвращает относительный путь по умолчанию, но -eпереключатель исправляет это.
Денис
Какой будет команда для OSX?
Игорь Маркелов
@IgorMarkelov Извините, но я понятия не имею, когда речь заходит об OSX.
Деннис
1
На Mac это: brew install coreutilsа find * -type l -exec bash -c 'ln -f "$(greadlink -m "$0")" "$0"' {} \;.
Игорь Маркелов