У меня есть куча символических ссылок на другой диск. Мне нужно переместить все файлы с этого диска, на которые есть ссылки в другом месте, чтобы я мог удалить его.
Марти Тренут
Ответы:
14
Для некоторых определений «легкий»:
#!/bin/shset-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 {} +
Спасибо за редактирования, Anon, но скрипт делает ручки имена файлов с пробелами просто отлично, цитируя переменные во всех необходимых местах. Переключение "$var"на "${var}"noop в sh / bash. Я удалил один bashism ( [[), остальное совместимо с POSIX sh.
Гравитация
Еще более надежный метод обработки сбоев символьных ссылок заключается во cpвременном файле в том же каталоге, mv -fчто и временный файл в исходном. Это следует остерегаться проблемами , как люди , удерживая Ctrl-Cили заполнение файловой системы до между rmи cpкоманды (таким образом предотвращая даже новый lnот работы). Временные имена файлов легко обнаружить ls -aдля последующей очистки, если это необходимо.
Мистер Фуз
Как примечание, я серьезно не могу вспомнить, почему я не просто использовал abstarget=$(readlink -f "$link")вместо блока case , но это могло быть причинами переносимости.
Гравитация
17
Возможно, будет проще использовать 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
Спасибо - почти то, что мне было нужно: я должен был сделать что-то вроде: cp -L files tmp/ && rm files && cp tmp/files . если вы поясните, вы, вероятно, поможете большему количеству людей ...
мудрец
5
"Легко" будет функцией от вас, скорее всего.
Вероятно, я бы написал скрипт, который использует утилиту командной строки find для поиска символически связанных файлов, а затем вызывает rm и cp для удаления и замены файла. Вы, вероятно, преуспели бы в том, чтобы также вызывать действие, вызываемое проверкой поиска, что осталось достаточно свободного места перед перемещением ссылки sym.
Другое решение может состоять в том, чтобы смонтировать файловую систему через что-то, что скрывает ссылки sym (например, samba), а затем просто скопировать все из этого. Но во многих случаях подобное может привести к другим проблемам.
Более прямой ответ на ваш вопрос, вероятно, «да».
Редактировать: согласно запросу для более конкретной информации. Согласно man-странице для find , эта команда выведет список всех файлов ссылок sym на глубину 2 каталогов, из /:
find /-maxdepth 2-type l -exec ./ReplaceSymLink.sh {} \;
Я считаю, что это вызовет какой-то скрипт, который я только что составил, и передам имя файла, который вы только что нашли. В качестве альтернативы, вы можете записать результаты поиска в файл (используйте «find [blah]> symlinks.data» и т. Д.), А затем передать этот файл в сценарий, который вы написали, для изящного копирования оригинала.
Это идет, чтобы найти элементы, и тот, помеченный как ответ, используется для замены ссылок!
Марти Тренут
3
Это единственная возможность, которую я использовал: предположим, что все локальные файлы являются ссылками на другой файл в «источнике». Вы можете уточнить выбор файла с помощью шаблонов или «найти». Пожалуйста, поймите, прежде чем использовать.
для f в *; do cp --remove-destination source / $ f $ f; сделанный
как насчет использования readlink: для f в *; do cp ---- remove-destination "$ (readlink $ f)" "$ f"; сделано
Диего
Да, это хорошая идея, но вы теряете контроль над операцией. Одним из ограничений моего решения является то, что оно не работает для файлов с пробелами в середине или для очень длинных списков. Вероятно, окончательное решение состоит в том, чтобы собрать вышеприведенный 'find --exec' и 'delete destination'. Кто-нибудь хочет попробовать?
MastroGeppetto
пробелы в середине следует уменьшить, поставив "$ f" в двойных кавычках. Вот как я использую его с «find & xargs» вместо «for loop»: find ./ -type l -print0 | xargs -0 -n1 -i sh -c 'cp --remove-destination $ (readlink "{ } ")" {} "'Я разместил это как отдельный ответ для видимости. superuser.com/a/1329543/499386
Диего
2
find .-type l -exec cp --dereference --recursive '{}''{}'.dereferenced \;
Создает копию каждого файла / папки с символьными ссылками <filename>.dereferenced, что более безопасно (если менее удобно), чем простая их замена. Перемещение скопированных данных в имена файлов символических ссылок оставлено читателю в качестве упражнения.
Небольшое улучшение поможет найти символические ссылки: для lnk в `find. -тип l`; do src = $ (readlink $ lnk) && rm $ lnk && mv $ src $ lnk; сделано (не проверено с иерархией, но будьте осторожны с обратными метками)
Roman Susi
1
У меня была такая же проблема со ссылками на копирование в gwenview, когда вы обычно ожидали, что она перейдет по ссылке и скопирует файл.
То, что я сделал, чтобы «очистить» каталог, перейдя по всем ссылкам и скопировав все указанные файлы в каталог, - это создать «чистый» каталог, запустить, например,
"for file in `ls`; do cp -L $file scratchdir/$file; done; mv scratchdir/* ./"
это слишком опасно для сценария, так как нет проверки, но это решило мою проблему.
Ответы:
Для некоторых определений «легкий»:
Запустите этот скрипт с именами ссылок в качестве аргументов, например, через
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 для копирования данных в новый каталог.
Вы могли бы использовать что-то вроде этого
источник
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 [blah]> symlinks.data» и т. Д.), А затем передать этот файл в сценарий, который вы написали, для изящного копирования оригинала.
источник
-exec ./ReplaceSymLink.sh {} \;
Это единственная возможность, которую я использовал: предположим, что все локальные файлы являются ссылками на другой файл в «источнике». Вы можете уточнить выбор файла с помощью шаблонов или «найти». Пожалуйста, поймите, прежде чем использовать.
Надеюсь это поможет
источник
Создает копию каждого файла / папки с символьными ссылками
<filename>.dereferenced
, что более безопасно (если менее удобно), чем простая их замена. Перемещение скопированных данных в имена файлов символических ссылок оставлено читателю в качестве упражнения.источник
Используя некоторые из предыдущих идей, следующая команда рекурсивно заменит каждую символическую ссылку на копию оригинала:
источник
на основе /superuser//a/1301199/499386 MastroGeppetto
источник
Там много хороших ответов, но я так как вы искали что-то легкое
источник
У меня была такая же проблема со ссылками на копирование в gwenview, когда вы обычно ожидали, что она перейдет по ссылке и скопирует файл.
То, что я сделал, чтобы «очистить» каталог, перейдя по всем ссылкам и скопировав все указанные файлы в каталог, - это создать «чистый» каталог, запустить, например,
это слишком опасно для сценария, так как нет проверки, но это решило мою проблему.
источник
источник
Я сделал однострочную версию, так как мой веб-отель не разрешал bash-скрипты, и он работал нормально для меня:
источник