Заменить все символические ссылки на оригинальные
У меня есть следующая структура каталогов
/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
Как бы это сделать?
Ответы
Ответ 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