Удивительное расширение оболочки при усечении переменной, полученной звездочкой
В моей папке у меня есть следующие файлы:
roi_1_Precentral_L/
roi_1_Precentral_L_both.fig
roi_1_Precentral_L_left.fig
roi_1_Precentral_L_right.fig
roi_1_Precentral_L_slice.fig
roi_2_Precentral_R/
roi_2_Precentral_R_both.fig
...
roi_116_Vermis_10/
roi_116_Vermis_10_both.fig
roi_116_Vermis_10_left.fig
roi_116_Vermis_10_right.fig
roi_116_Vermis_10_slice.fig
Я использую следующий скрипт для получения желаемого префикса имени файла для каждого из 116 типов:
for iroi in `seq 1 116`;
do
d=roi_${iroi}_*/
d2=${d:0:-1} # <-- THIS LINE IS IMPORTANT
echo $d2
done;
Желаемый вывод для iroi = 1:
$ roi_1_Precentral_L
Фактический вывод:
$ roi_1_Precentral_L roi_1_Precentral_L_both.fig roi_1_Precentral_L_left.fig roi_1_Precentral_L_right.fig roi_1_Precentral_L_slice.fig
Как можно избежать расширения оболочки в выделенной строке кода для получения желаемого результата?
2 ответа
Если вы присваиваете массиву, глобус будет развернут в первой строке, а не позже echo
как было с вашим оригинальным кодом.
d=( "roi_${iroi}_"*/ )
d2=${d:0:-1} # Note that this only works with new bash. ${d%/} would be better.
echo "$d2"
Если вы ожидаете несколько каталогов, "${d[@]%/}"
развернем до полного списка, с трейлингом /
снято с каждого:
d=( "roi_${iroi}_"*/ )
printf '%s\n' "${d[@]%/}"
Что касается избежания нежелательных расширений - обратите внимание, что в приведенном выше описании каждое расширение, за исключением тех, которые находятся в правой части простого (строка, а не массив) назначения, заключено в двойные кавычки. (Регулярные присваивания неявно запрещают расщепление строк и расширение глобуса - хотя даже тогда не помешает иметь кавычки! ${d:0:-1}
удалял /
из самого выражения глобуса, а не из его результатов).
Ответ на вопрос
Если вы хотите, вы можете цитировать, чтобы избежать расширения *
в $d
...
d=roi_${iroi}_*/
d2="${d:0:-1}"
echo $d2
... но тогда вы могли бы напрямую написать...
d2="roi_${iroi}_*"
echo $d2
... и результат будет таким же, как в вашем вопросе.
Ответ на ожидаемый результат
Вы можете выполнить расширение в массиве и выбрать первую запись массива, а затем удалить /
из этой записи.
for iroi in {1..116}; do
d=(roi_"$iroi"_*/)
d2="${d[0]:0:-1}"
echo "$d2"
done
Это соответствует только каталогам и печатает первый каталог без завершающего /
,