Чи є простий спосіб замінити всі символічні посилання файлом, на який вони посилаються?
Чи є простий спосіб замінити всі символічні посилання файлом, на який вони посилаються?
Відповіді:
Для деяких визначень поняття "легко":
#!/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. Я видалив один башизм ( [[
), решта сумісна з POSIX sh.
cp
посилань є тимчасовий файл у тому самому каталозі, а потім mv -f
тимчасовий файл у оригіналі. Це повинно захищати від таких проблем, як утримування людей Ctrl-C
або заповнення файлової системи між командами rm
та cp
(тим самим не дозволяючи навіть новим ln
працювати). Тимчасові імена файлів легко помітити ls -a
для подальшої очистки, якщо потрібно.
abstarget=$(readlink -f "$link")
замість блоку регістру , але це, можливо, було причиною переносимості.
Можливо, простіше використовувати 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 для пошуку , ця команда буде перераховувати всі файли символьних посилань на глибину до 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 - вихідний джерело призначення / $ 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