Есть ли простой способ заменить все символические ссылки файлом, на который они ссылаются?
Есть ли простой способ заменить все символические ссылки файлом, на который они ссылаются?
Ответы:
Для некоторых определений «легкий»:
#!/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 {} +
"$var"
на "${var}"
noop в sh / bash. Я удалил один bashism ( [[
), остальное совместимо с POSIX sh.
cp
временном файле в том же каталоге, mv -f
что и временный файл в исходном. Это следует остерегаться проблемами , как люди , удерживая Ctrl-C
или заполнение файловой системы до между rm
и cp
команды (таким образом предотвращая даже новый ln
от работы). Временные имена файлов легко обнаружить ls -a
для последующей очистки, если это необходимо.
abstarget=$(readlink -f "$link")
вместо блока case , но это могло быть причинами переносимости.
Возможно, будет проще использовать 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
tar -hcf - sourcedir | tar -xf - -C newdir
cp -L
это более простое решение
cp
реализации будут копировать каталоги.
Если я вас правильно понял, -L
флаг cp
команды должен делать именно то, что вы хотите.
Просто скопируйте все символические ссылки, и он заменит их файлами, на которые они указывают.
cp -L files tmp/ && rm files && cp tmp/files .
если вы поясните, вы, вероятно, поможете большему количеству людей ...
"Легко" будет функцией от вас, скорее всего.
Вероятно, я бы написал скрипт, который использует утилиту командной строки 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» и т. Д.), А затем передать этот файл в сценарий, который вы написали, для изящного копирования оригинала.
-exec ./ReplaceSymLink.sh {} \;
Это единственная возможность, которую я использовал: предположим, что все локальные файлы являются ссылками на другой файл в «источнике». Вы можете уточнить выбор файла с помощью шаблонов или «найти». Пожалуйста, поймите, прежде чем использовать.
для f в *; do cp --remove-destination source / $ f $ f; сделанный
Надеюсь это поможет
find . -type l -exec cp --dereference --recursive '{}' '{}'.dereferenced \;
Создает копию каждого файла / папки с символьными ссылками <filename>.dereferenced
, что более безопасно (если менее удобно), чем простая их замена. Перемещение скопированных данных в имена файлов символических ссылок оставлено читателю в качестве упражнения.
find ./ -type l -print0|xargs -0 -n1 -i sh -c 'cp --remove-destination $(readlink "{}") "{}" '
на основе /superuser//a/1301199/499386 MastroGeppetto
Там много хороших ответов, но я так как вы искали что-то легкое
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/* ./"
это слишком опасно для сценария, так как нет проверки, но это решило мою проблему.
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