Я хочу действовать в списке подкаталогов в каталоге. Рассматривать:
for x in x86-headers/*/C/populate.sh; do echo $x; done
Это дает
x86-headers/elf/C/populate.sh
x86-headers/gl/C/populate.sh
x86-headers/gmp/C/populate.sh
x86-headers/gnome2/C/populate.sh
x86-headers/gtk2/C/populate.sh
x86-headers/jni/C/populate.sh
x86-headers/libc/C/populate.sh
Но я хочу значения, соответствует второй части пути,
elf
, gl
и т.д. Я знаю , как сдирать ведущий x86-headers
.
for x in x86-headers/*/C/populate.sh; do i=${x##x86-headers/}; echo $i; done
который дает
elf/C/populate.sh
gl/C/populate.sh
gmp/C/populate.sh
gnome2/C/populate.sh
gtk2/C/populate.sh
jni/C/populate.sh
libc/C/populate.sh
Я также знаю, как избавиться от более поздних сроков в пути. Т.е. спускаясь на один уровень:
cd x86-headers
for x in */C/populate.sh; do i=${x%%/*}; echo $i; done
дает
elf
gl
gmp
gnome2
gtk2
jni
libc
Но попытка объединить это не работает. Т.е.
for x in x86-headers/*/C/populate.sh; do i=${${x##x86-headers}%%/*}; echo $i; done
дает
bash: ${${x##x86-headers}%%/*}: bad substitution
Без сомнения, это неправильный синтаксис, но я не знаю правильный синтаксис. Конечно, могут быть лучшие способы сделать это. Если бы я использовал Python, я бы использовал split on, /
чтобы разбить каждый путь на список, а затем выбрать второй элемент, но я не знаю, как это сделать в bash.
РЕДАКТИРОВАТЬ: Спасибо за ответы. Я должен был также спросить, возможно ли сделать это переносимо, и если да, то как?
i=${x#*/}; i=${i%%/*}
необязательна, верно?ash
/,dash
будут выполнять назначения справа налево (именно так велась оболочка Борна) и вызывать проблемы в этом случае.Расширение параметров не позволяет вам вкладывать выражения, поэтому вы вынуждены сделать это в два шага с присваиванием:
У вас есть возможность использовать массивы здесь, но я думаю, что это будет более громоздким, чем приведенный выше PE:
Тогда есть третий вариант использования внешних команд. С коротким списком файлов это, как правило, наименее эффективный вариант, но он будет лучше масштабироваться при увеличении количества файлов:
источник
zsh
позволяет вкладывать.bash
.источник
Будьте очень осторожны, используя следующую конструкцию:
Как вы могли бы в конечном итоге делать
echo *
. В этом случае это только смешно, но это может быть гораздо хуже, если вы root, вашCWD
is,/
и вы хотите удалить некоторые подкаталоги/tmp
вместо того, чтобы повторять их!Чтобы исправить это в bash, вы можете сделать:
Обратите внимание
shopt -u nullglob
на в конце, чтобы восстановить поведение bash по умолчанию после цикла.Более портативное решение может быть:
( Подстановки
##
и%%
параметров действительны в ksh88 ).Перейдите по этой ссылке для более полного обсуждения nullglob .
Обратите внимание, что 3 решения выше не дают результатов, если у вас есть промежуточный каталог с пробелом в имени. Чтобы решить эту проблему, используйте двойные кавычки в подстановке переменных:
источник
Для переноса сопоставления с образцом в путевых именах вы можете установить для
IFS
переменной оболочки значение,/
а затем использовать расширение параметров оболочки.Выполнение всего этого в подоболочке помогает сохранить среду родительской оболочки неизменной!
источник