Я пытаюсь создать сценарий bash, который находит все файлы в моем каталоге dotfiles и связывает их с символическими ссылками в ~. Если каталог, в котором находится файл, не существует, он должен быть создан.
Скрипт в его нынешнем виде просто пытается найти файлы и создать два пути, когда это сработает, с ln -s
будут использоваться «реальный» и «символическая ссылка». Однако при попытке сохранить строки в "реальных" и "символических" ссылках все, что я получаю, это line 12: ./.zshrc: Permission denied
Что я делаю не так?
#!/bin/bash
dotfiles=()
readarray -d '' dotfiles < <(find . -type f ! -path '*/.git/*' ! -name "README.md" -type f -print0)
for file in ${dotfiles[@]}; do
dir=$(dirname $file | sed s#.#$HOME#1)
[ ! -d $dir ] && echo "directory $dir not exist!" && mkdir -p $dir
# Create path strings
real=$("$file" | sed s#.#$PWD#1)
symlink=$("$file" | sed s#.#$HOME#1)
echo "Real path: $cur"
echo "Symbolic link path: $new"
done
exit
P.S, я - bash noob и в основном пишу этот сценарий в качестве учебного опыта.
1 ответ
Вот рефакторинг, который пытается исправить очевидные проблемы. Подробнее см. Комментарии с # ...
. Возможно, также обратитесь к http://shellcheck.net/, прежде чем обращаться за помощью.
Непосредственной причиной сообщения об ошибке является то, что $("$file" ...)
действительно пытается запустить $file
как команду и записать ее вывод. Вы, вероятно, имели в виду $(echo "$file" ...)
, но этого часто можно избежать.
#!/bin/bash
dotfiles=()
readarray -d '' dotfiles < <(find . -type f ! -path '*/.git/*' ! -name "README.md" -type f -print0)
# ... Fix broken quoting throughout
for file in "${dotfiles[@]}"; do
dir=$(dirname "$file" | sed "s#^\.#$HOME#") # ... 1 is not required or useful
# ... Use standard error for diagnostics
[ ! -d "$dir" ] && echo "$0: directory $dir does not exist!" >&2 && mkdir -p "$dir"
# Create path strings
# ... Use parameter substitution
real=$PWD/${file#./}
symlink=$HOME/${$file#./}
# ... You mean $real, not $cur?
echo "Real path: $real"
# ... You mean $symlink, not $new?
echo "Symbolic link path: $symlink"
done
# ... No need to explicitly exit; trust me, you will anyway
#exit
Это просто синтаксические исправления; Я, вероятно, не стал бы хранить результаты из find
в массиве и просто перебирал их напрямую, и я не проверял, действительно ли логика делает то, что (мы можем предположить) вы, возможно, пытаетесь сделать.
См. Также Цикл по парам значений в bash по аналогичной теме, и Когда следует заключать в кавычки переменную оболочки?.
У сценария все еще есть досадное предположение, что он будет запущен в каталоге dotfiles. Вероятно, лучшим решением было бы явно запустить find
в этом каталоге и провести соответствующий рефакторинг.
sed 's/x/y/'
заменит первое вхождение x
на y
в каждой строке по определению и дизайну; нет причин или необходимости явно добавлять 1
после последнего разделителя. (Некоторые варианты sed
позволяют выбрать число, отличное от первого, но это не переносимо; и, конечно, указывать первое совпадение, когда оно уже является значением по умолчанию, просто глупо. Существует {{X5} } для замены всех совпадений, а не только первого, который многие новички хотят использовать везде, но, конечно, здесь это тоже не нужно и не полезно.)
Похожие вопросы
Связанные вопросы
Новые вопросы
bash
Этот тег предназначен для вопросов о сценариях, написанных для командной оболочки Bash. Сценарии оболочки с синтаксисом или другими ошибками, пожалуйста, проверьте их на https://shellcheck.net, прежде чем публиковать здесь. Вопросы об интерактивном использовании Bash, скорее всего, будут актуальны на Unix & Linux Stack Exchange или Super User, чем на Stack Overflow.