Сценарий для замены всех символьных ссылок на цель для указания на другую цель (в том же каталоге)

Одним общим элементом, который Вы ищете, является FUSE, gvfs GNOME, например, использование, что под капотом 1 Это - интерфейс с ядром, и я полагаю, что это характерно для всех непривилегированных (автоматических) систем монтирования на Linux [но см. комментарии]. Человек DE не создал бы их собственную версию этого, так как это потребует исправления ядра.

Та ссылка домашней страницы на самом деле устарела, потому что, как отмечено здесь, FUSE стал частью официального ядра несколько лет назад, но это действительно описывает источники и цели проекта (это не только для непривилегированного монтирования).

Причиной, которую различные системы могут отклонить в стиле вне этого, является та же причина, у Вас есть различные настольные среды: они представляют различные видения того, как/какой GUI должен быть. Они заботятся о форме и функции пользовательского интерфейса, но FUSE делает фактическое монтирование и материал уровня ядра. Обратите внимание, что FUSE действительно не делает "автоматической" части, это больше о "непривилегированной" части, но автозапчасть довольно проста: все, что необходимо сделать, опросить, например, /dev. Я записал монтирующееся приложение, которое прокладывает себе путь; это просто наблюдает за появлением новых узлов 2, Что часть является, возможно, приблизительно ста строками C++. Легкий-peasy - никакая реальная потребность в общем API на том уровне.

1Or может, если это делает действительно непривилегированное монтирование. Ответ Teresa может касаться более новых подходов к предоставлению доступов к нормальному монтированию.

2As hildred наблюдает, udev обратные вызовы было бы лучшее, меньше метода взлома.

3
08.12.2014, 07:02
2 ответа

Я предполагаю, что вы используете Bash, поэтому я бы использовал Globstar для цикла через все каталоги сразу с ** . После этого все то, что осталось, это играть немного с ReadLink , RealPath и т. Д.:

shopt -s globstar
for file in c1/** d1/**; do
    if [[ -h "$file" ]]; then
        if [[ "$(readlink -f "$file")" == "$(realpath a/b/original-target)" ]]; then
            ln -sf "$(dirname "$(readlink "$file")")"/new-target "$(dirname "$file")" && rm -f "$file"
        fi
    fi
done
2
27.01.2020, 21:23

pax может быть действительно полезным в этих случаях. На самом деле было бы проще, если бы я мог обнаружить pax , который выполняет -o listopt = ... параметр , указанный в POSIX , но, несмотря на мои взгляды, Я еще не нашел ни одного. Я использую один из поддерживаемых mirabilos - BSD pax ( mirabipax ?) , который, насколько мне известно, является, вероятно, наиболее распространенным. В любом случае вы получите регулярное выражение имен файлов и списков файлов. Например:

(set -e; mkdir -p a/b c1/c2 d1/d2/d3
touch a/b/original-target a/b/new-target
cd c1/c2; ln -s ../../a/b/original-target
cd ../../d1/d2/d3; ln -s ../../../a/b/original-target)

Это делает ваше дерево. Теперь я перечислю его:

pax -ws'|\(\..*/original-target.*\)*.*|\1|' ././ | 
pax -cvs'|\(.*\)/original|\1/new|p' \
     '././a/b/original-target' '*/original-target?*'

Который печатает ...

././d1/d2/d3/original-target >> ././d1/d2/d3/new-target
lrwxrwxrwx  1 mikeserv mikeserv         0 Dec  7 18:17 ././d1/d2/d3/new-target => ../../../a/b/new-target
././c1/c2/original-target >> ././c1/c2/new-target
lrwxrwxrwx  1 mikeserv mikeserv         0 Dec  7 18:14 ././c1/c2/new-target => ../../a/b/new-target

Итак, первый pax записывает архив ustar в stdout . Аргу регулярного выражения -s , который я передал, чаще всего используется для изменения имен файлов в потоке - как я это делаю здесь со вторым pax - но с некоторыми хитростями его также можно используется в первую очередь для фильтрации файлов, добавляемых в архив.

Видите ли, любое имя файла, которое оказывается пустым после применения аргумента -s , указывается для полного удаления из архива. Поэтому я использую регулярное выражение, которое будет соответствовать каждому имени файла, но также удаляю каждый символ из каждого, который не соответствует шаблону, сохраненному в \ 1 . Это необходимо, потому что, хотя вы можете легко выбирать файлы в архиве на основе шаблона, это не тот случай, когда -w запускает архив, который зависит от глобусов оболочки и поэтому не выполняет рекурсию.

Тем не менее, регулярное выражение в том виде, в котором оно написано, по-прежнему будет иметь / original-target , за которым следует любой символ, и поэтому на другом конце один из шаблонов I -c в моем выбор при выводе в список архива - * / original-target? * - он отбрасывается туда. Даже это не идеально - я имею в виду, может быть, у вас есть ссылки, которые содержат этот шаблон дважды, но ... ну, это то, что есть - и это довольно хорошо. С этим можно справиться с дальнейшим тестированием по тем же принципам. Во всяком случае, я также -c добавляю соответствие к самому ././ a / b / original-file - и поэтому он также удаляется из вывода списка.

В режиме списка - это то, что делает pax , когда не -r ead или -w rite - pax списки подробно - в формате ls -l - включая любые целевые объекты программных ссылок, такие как link => target - но только после применения любых применимых -s ] args. Те же самые аргументы -s печатаются независимо от -v , когда -s | ... | ... | p the p применяется в следующем формате:

«% s >>% s \ n», исходный путь , новый путь

Таким образом, выше мы получаем списки, разделенные знаком ././ которые иначе не появились бы. Надеюсь, вы согласитесь, теперь это действительно упрощает задачу.Я оставляю читателю решать, как можно применить данные такого рода с ln - это должно быть довольно просто - но вам даже не нужно этого делать .

Фактически, pax предназначен для того, чтобы вы могли изменять архив в r ead или w времени обряда с опциями cli для изменения таких вещей как пользователь, группа, данные ссылки, имя файла, источник файла и т. д. Это невероятно мощные инструменты синтаксического анализа файлов, но наиболее близким к pax , который их реализует, является GNU tar и только частично. Я не нашел никаких средств воздействия на типы файлов заголовков - хотя вы должны иметь возможность сделать это до некоторой степени - с помощью параметров cli, даже если это не так уж сложно с регулярным выражением в самом архиве. Для этого есть поле заголовка:

... 2 - представляет собой символическую ссылку. Содержимое символической ссылки должно храниться в поле имя ссылки .

Еще одна вещь, которую я действительно хочу, чтобы pax делал, - это -o listopt = ... . Вот фрагмент из раздела примеров спецификации:

Использование параметра:

-o listopt="%M %(atime)T %(size)D %(name)s"

... отменяет описание вывода по умолчанию в стандартном выводе и вместо этого пишет:

-rw-rw--- Jan 12 15:53 2003 1492 /usr/foo/bar

Использование параметров:

-o listopt='%L\t%(size)D\n%.7' \
-o listopt='(name)s\n%(atime)T\n%T'

... отменяет значение по умолчанию описание вывода в стандартном выводе и вместо этого пишет:

/usr/foo/bar -> /tmp   1492
/usr/fo
Jan 12 15:53 1991
Jan 31 15:53 2003

Итак, если вы наткнетесь на pax , который делает это ... ну, вы знаете, кто смотрит.

1
27.01.2020, 21:23

Теги

Похожие вопросы