Есть ли простой способ заменить все символические ссылки файлом, на который они ссылаются?
12 ответов
Возможно, будет проще использовать tar для копирования данных в новый каталог.
-H (c and r mode only) Symbolic links named on the command line will be followed; the target of the link will be archived, not the link itself.
Вы могли бы использовать что-то вроде этого
tar -hcf - sourcedir | tar -xf - -C newdir
tar --help:
-H, --format=FORMAT create archive of the given format
-h, --dereference follow symlinks; archive and dump the files they point to
Если я вас правильно понял, флаг -L
команды cp
должен делать именно то, что вы хотите.
Просто скопируйте все символические ссылки, и он заменит их файлами, на которые они указывают.
Для некоторых определений "легкий":
#!/bin/sh
set -e
for link; do
test -h "$link" || continue
dir=$(dirname "$link")
reltarget=$(readlink "$link")
case $reltarget in
/*) abstarget=$reltarget;;
*) abstarget=$dir/$reltarget;;
esac
rm -fv "$link"
cp -afv "$abstarget" "$link" || {
# on failure, restore the symlink
rm -rfv "$link"
ln -sfv "$reltarget" "$link"
}
done
Запустите этот скрипт с именами ссылок в качестве аргументов, например, через find . -type l -exec /path/tos/script {} +
"Легко" будет функцией от вас, скорее всего.
Возможно, я бы написал скрипт, который использует утилиту командной строки find для поиска символически связанных файлов, а затем вызывает rm и cp, чтобы удалить и заменить файл. Вы, вероятно, преуспели бы в том, чтобы также вызывать действие, вызываемое проверкой поиска, что достаточно свободного места перед перемещением ссылки sym.
Другое решение может состоять в том, чтобы смонтировать файловую систему через что-то, что скрывает ссылки sym (например, samba), а затем просто скопировать все из этого. Но во многих случаях подобное может привести к другим проблемам.
Более прямой ответ на ваш вопрос, вероятно, "да".
Редактировать: согласно запросу для более конкретной информации. Согласно man-странице для find, эта команда выведет список всех файлов ссылок sym на глубину до 2 каталогов, из /:
find / -maxdepth 2 -type l -print
Чтобы найти, чтобы выполнить что-то при поиске:
find / -maxdepth 2 -type l -exec ./ReplaceSymLink.sh {} \;
Я полагаю, что это вызовет какой-то скрипт, который я только что составил, и передам имя файла, который вы только что нашли. В качестве альтернативы, вы можете записать результаты поиска в файл (используйте «find [blah]> symlinks.data» и т.д.), А затем передать этот файл в сценарий, который вы написали, для корректного копирования оригинала.
Используя некоторые из предыдущих идей, следующая команда рекурсивно заменит каждую символическую ссылку на копию оригинала:
find . -type l -exec bash -c "echo 'Replacing {} ...'; cp -LR '{}' '{}'.dereferenced; rm '{}'; mv '{}'.dereferenced '{}'" \;
Это единственная возможность, которую я использовал: предположим, что все локальные файлы являются ссылками на другой файл в "источнике". Вы можете уточнить выбор файла с помощью шаблонов или "найти". Пожалуйста, поймите, прежде чем использовать.
для f в *; do cp --remove-destination source/$ f $ f; сделанный
Надеюсь это поможет
find . -type l -exec cp --dereference --recursive '{}' '{}'.dereferenced \;
Создает копию каждого файла / папки с символьными ссылками в <filename>.dereferenced
, что безопаснее (если менее удобно), чем просто их прямая замена. Перемещение скопированных данных в имена файлов символических ссылок оставлено читателю в качестве упражнения.
Там много хороших ответов, но я так как вы искали что-то легкое
for i in *; do link=$(readlink $i) && rm $i && mv $link $i; done
У меня была такая же проблема со ссылками на копирование в gwenview, когда вы обычно ожидали, что она перейдет по ссылке и скопирует файл.
То, что я сделал, чтобы «очистить» каталог, перейдя по всем ссылкам и скопировав все указанные файлы в каталог, - это создать «чистый» каталог, запустить, например,
"for file in `ls`; do cp -L $file scratchdir/$file; done; mv scratchdir/* ./"
это слишком опасно для сценария, так как нет проверки, но это решило мою проблему.
find ./ -type l -print0|xargs -0 -n1 -i sh -c 'cp --remove-destination $(readlink "{}") "{}" '
основанный на https://superuser.com/a/1301199/499386 MastroGeppetto
for f in *; do cp --remove-destination $(readlink "$f") "$f"; done
Я сделал однострочную версию, так как мой веб-отель не разрешал bash-скрипты, и он работал нормально для меня:
before:
> find . -type l | wc -l
358
> for link in `find . -type l` ; do echo "$link : "; ls -al $link ; cp $link notalink; unlink $link; mv notalink $link ; ls -al $link; done
...
after:
> find . -type l | wc -l
0