Bash скрипт для безопасного создания символических ссылок? - PullRequest
9 голосов
/ 08 августа 2010

Я пытаюсь сохранить все мои файлы конфигурации профиля (~ / .xxx) в git. Я довольно ужасен в написании сценариев bash, но я думаю, что это будет довольно просто для вас, гуру сценариев.

По сути, мне нужен скрипт, который будет создавать символические ссылки в моем домашнем каталоге на файлы в моем репо. Твист, я бы хотел, чтобы он предупреждал и запрашивал перезапись, если символическая ссылка будет перезаписывать реальный файл. Также должно появиться сообщение о том, что sym-ссылка будет перезаписана, но целевой путь отличается.

Я не против вручную редактировать скрипт для каждой ссылки, которую я хочу создать. Меня больше беспокоит возможность быстрого развертывания новых конфигурационных скриптов с помощью запуска этого скрипта, хранящегося в моем репо.

Есть идеи?

Ответы [ 2 ]

14 голосов
/ 08 августа 2010

Команда ln уже достаточно консервативна в отношении удаления, поэтому, возможно, подход KISS достаточно хорош для вас:

ln -s git-stuff/home/.[!.]* .

Если файл или ссылка уже существует, вы получите сообщение об ошибке иэта ссылка будет пропущена.

Если вы хотите, чтобы файлы имели другое имя в вашем хранилище, передайте параметр -n в ln, чтобы он случайно не создал символическую ссылку в существующем подкаталоге.с таким именем:

ln -sn git-stuff/home/profile .profile
...

Если вы также хотите иметь ссылки в подкаталогах вашего домашнего каталога, cp -as воспроизводит структуру каталога, но создает символические ссылки для обычных файлов.С опцией -i он запрашивает, если цель уже существует.

cp -i -as git-stuff/home/.[!.]* .

(Мой ответ предполагает GNU ln и GNU cp, такие как вы найдете в Linux (и Cygwin)но обычно не в других подразделениях.)

1 голос
/ 08 августа 2010

Следующее имеет условия гонки, но это, вероятно, настолько же безопасно, как вы можете получить без транзакций файловой системы:

# create a symlink at $dest pointing to $source
# not well tested
set -e   # abort on errors
if [[ ( -h $dest && $(readlink -n "$dest") != $source ) || -f $dest || -d $dest ]]
then
    read -p "Overwrite $dest? " answer
else
    answer=y
fi
[[ $answer == y ]] && ln -s -n -f -v -- "$source" "$dest"
...