Я только что снова столкнулся с этим вариантом использования; Я кратко расскажу, как я с этим справился.
Я хотел загрузить (но не установить) Git и PostgreSQL, а затем установить их во время процесса бродячей подготовки.
Я использовал следующую команду со свежей виртуальной машины, чтобы загрузить пакеты со всеми зависимостями (после sudo mkdir / vagrant / packages
):
sudo yumdownloader --destdir=/vagrant/packages/ --resolve -y git postgresql
Уловка с этой командой в том, что она загружает слишком много . Следующим шагом было установить RPM, которые мне на самом деле были необходимы для установки. Я сделал это, попробовав:
sudo yum install /vagrant/packages/git-1.7.1-4.el6_7.1.x86_64.rpm /vagrant/packages/postgresql-8.4.20-6.el6.x86_64.rpm
И нажав «Нет» в запросе подтверждения, потому что я мог видеть, что он планирует загрузку зависимостей. Я взял перечисленные зависимости и добавил их в свою команду:
sudo yum install /vagrant/packages/git-1.7.1-4.el6_7.1.x86_64.rpm /vagrant/packages/postgresql-8.4.20-6.el6.x86_64.rpm /vagrant/packages/perl-* /vagrant/packages/postgresql-libs-8.4.20-6.el6.x86_64.rpm
Это будет успешно работать без загрузки, поэтому я запустил:
cd /vagrant/packages/
mkdir save
mv /vagrant/packages/git-1.7.1-4.el6_7.1.x86_64.rpm /vagrant/packages/postgresql-8.4.20-6.el6.x86_64.rpm /vagrant/packages/perl-* /vagrant/packages/postgresql-libs-8.4.20-6.el6.x86_64.rpm save/
rm *.rpm
mv save/* .
rmdir save
Результат: каталог "packages" с только действительно необходимыми зависимостями из свежего изображения Vagrant.
Затем, добавив команду подготовки оболочки к моему Vagrantfile
:
config.vm.provision "shell", inline: <<-SHELL
yum install -C -y /vagrant/packages/*
SHELL
... У меня установлены Git и PostgreSQL, которые готовы к использованию после любого бродяг
, даже если vagrant destroy
был запущен.
Эта функция bash выполняет перебор -принудительно find
по всем уровням каталогов под текущим каталогом в поисках именованного каталога.
cdd() {
if [ "$#" -ne 1 ]
then
printf '%s: Error: one directory name expected\n' "${FUNCNAME[0]}" >&2
return
fi
maxdepth=$(find. -type d -exec sh -c 'printf %s "$1" | LC_ALL=C tr -dc / | wc -c' findshell {} \; | sort -n | tail -1)
for((i=1; i <= maxdepth; i++))
do
dir=$(find. -mindepth "$i" -maxdepth "$i" -type d -name "$1")
if [ -n "$dir" ]
then
command cd -- "$dir"
return
fi
done
printf '%s: %s: no such directory found\n' "${FUNCNAME[0]}" "$1" >&2
}
Первая команда find
выполняет фрагмент оболочки для каждого каталога в текущем каталоге; фрагмент оболочки выводит имя каталога в конвейер tr
и wc
, который удаляет каждый символ, не являющийся косой чертой -, а затем подсчитывает количество косых черт -. Я перенял этот трюк у ilkkachu и Stéphane Chazelas здесь . После вывода всех глубин каталога мы sort | tail
находим наибольшее число. Это число является максимальной глубиной каталога, в которой нам нужно искать.
После этого выполняется цикл по find
, ограниченный точно каждой глубиной каталога по очереди, начиная с текущего каталога до самого глубокого каталога. Если совпадение найдено, мы cd
и выходим из функции. Если совпадений не найдено, мы выходим из цикла и выводим сообщение в stderr.
С помощью zsh
можно сделать:
cdd() cd -- **/$1(/Od[1])
cdd themes
Эта функция cdd
находит все файлы типа каталога(/
)с именем, заданным в качестве аргумента ($1
), O
упорядочивает их по d
epth и выбирает первый([1]
).
Не очень эффективным является то, что он сканирует все дерево каталогов (, пропуская скрытые каталоги, добавьте квалификатор D
glob, чтобы изменить это ), даже если в текущем каталоге есть соответствующий каталог.
Чтобы пройти по дереву каталогов на один уровень глубины за раз, вы можете вместо этого:
cdd() {
local dirs matches
dirs=(.)
while (($#dirs)) {
matches=($^dirs/$1(N/[1]))
if (($#matches)) {
cd $matches[1]
return
}
dirs=($^dirs/*(/N))
}
print >&2 Not found
return 1
}