Я хочу поместить команду в сценарий оболочки, который создаст символическую ссылку на каталог, но этот сценарий можно запускать снова и снова, поэтому при последующих вызовах команда не должна ничего менять.
Вот структура каталогов:
% tree /tmp/test_symlink
/tmp/test_symlink
├── foo
└── repo
└── resources
└── snippets
├── php.snippets
├── sh.snippets
├── snippets.snippets
├── sql.snippets
└── vim.snippets
Я хочу создать символическую ссылку в foo/
названных фрагментах, которая указывает на каталог /tmp/test_symlink/repo/resources/snippets
.
Итак, я бегу:
% ln -sfv /tmp/test_symlink/repo/resources/snippets /tmp/test_symlink/foo/snippets
'/tmp/test_symlink/foo/snippets' -> '/tmp/test_symlink/repo/resources/snippets'
что дает желаемый результат.
% tree /tmp/test_symlink
/tmp/test_symlink
├── foo
│ └── snippets -> /tmp/test_symlink/repo/resources/snippets
└── repo
└── resources
└── snippets
├── php.snippets
├── sh.snippets
├── snippets.snippets
├── sql.snippets
└── vim.snippets
5 каталогов, 5 файлов
Однако, когда команда запускается снова,
% ln -sfv /tmp/test_symlink/repo/resources/snippets /tmp/test_symlink/foo/snippets
'/tmp/test_symlink/foo/snippets/snippets' -> '/tmp/test_symlink/repo/resources/snippets'
он создает символическую ссылку на каталог, где aleady символическая ссылка существует, помещает символическую ссылку в настоящий каталог
% tree /tmp/test_symlink
/tmp/test_symlink
├── foo
│ └── snippets -> /tmp/test_symlink/repo/resources/snippets
└── repo
└── resources
└── snippets
├── php.snippets
├── sh.snippets
├── snippets -> /tmp/test_symlink/repo/resources/snippets
├── snippets.snippets
├── sql.snippets
└── vim.snippets
почему это происходит и как я могу изменить команду, чтобы последующие вызовы не создавали этот странный эффект?
источник
-n, --no-dereference treat LINK_NAME as a normal file if it is a symbolic link to a directory
.-T, --no-target-directory treat LINK_NAME as a normal file always
Как вы думаете, лучше всегда рассматривать символическую ссылку как файл? Я бы подумал, что будет лучше ограничить использование этих «специальных» опций?-T
как вы делаетеln
идемпотент. Существуют и другие способы получения того же результата, если вы предпочитаете, например, удаление ссылки и ее повторное создание, или если вы знаете, что онаfoo
уже существуетln -sfv /tmp/test_symlink/repo/resources/snippets /tmp/test_symlink/foo/
(на самом деле это может быть лучший ответ, я обновлю).if
операторы для обнаружения наличия символической ссылки и пропуска команды, если символическая ссылка существовала, но скрипты в итоге оказывались загроможденными и трудными для чтения, я собирался сделать что-то идемпотентное, но простое, например, не использоватьmkdir -p
никаких тестов , нет логики, просто хорошие лайнеры :)-T
, но конец моего ответа представляет другое решение, которое не использует-T
.Лучшее, что я могу сказать о том, что здесь происходит, это то, что на втором проходе
ln
команда ведет себя какcp
илиmv
, то есть если она видит «каталог» в <destination>, она поместит в нее файл, в противном случае, если <destination> нет существует, это сделает <назначение>. (это то, чего избегает трюк «slashdot» - то есть он будет гарантировать, что <destination> существует и является каталогом).Но я могу ошибаться.
В любом случае это, кажется, работает
источник