Нам действительно не следует открывать входной файл на стандартный вывод. (Вам нужно exec
до этого перенаправления, чтобы оно работало. Но это, вероятно, все равно не удастся и заблокирует ). Если вы хотите открыть файл с помощью fd, просто используйте 3 или что-то в этом роде.
exec 3<filename
# do something with fd 3
exec 3<&-
Можно перенаправить на fd 0 (stdin ), но если вы выполняете fd 0, чтобы указать куда-то еще, то вы должны сначала сохранить его.
exec 3<&0
exec < filename
# do something with the file on fd 0
# restore stdin, free fd3
exec 0<&3 3<&-
Если бы у нас было имя swu_run1_P_277_Vol_1.nii
в переменной name
, то ${name##*_}
было бы1.nii
(удаляется самая длинная строка префикса, соответствующая *_
).
Принимая это и удаляя .nii
, мы получаем число, которое мы хотим обнулить -заполнить до ширины трех символов:
name=swu_run1_P_277_Vol_1.nii
number=${name##*_}
number=${number%.nii}
В оболочке bash
самый простой способ (возможно )до нуля -заполнить число с помощьюprintf
:
printf '%.3d' "$number" # would print 001 (with no newline)
Одновременно мы можем построить новое имя:
printf '%s_%.3d.nii' "${name%_*.nii}" "$number"
Эта команда printf
напечатала бы swu_run1_P_277_Vol_001.nii
, удалив строку суффикса, которая соответствует _*.nii
из исходного имени, добавив _
и нулевое заполненное число -, а затем строку суффикса .nii
.
В довершение всего, мы можем вывести результирующую строку непосредственно в новую переменную с printf -v newname...
.
Объединяем это в одно имя:
name=swu_run1_P_277_Vol_1.nii
number=${name##*_}
number=${number%.nii}
printf -v newname '%s_%.3d.nii' "${name%_*.nii}" "$number"
Тогда это просто вопрос mv "$name" "$newname"
.
Итак, как это сделать для всех соответствующих файлов?
Предположим, что все соответствующие файлы соответствуют шаблону подстановки *Vol_*.nii
, тогда с помощью find
,
find. -type f -name '*Vol_*.nii' -exec bash -c '
for pathname do
dirpath=${pathname%/*} # or: dirpath=$(dirname "$pathname")
name=${pathname##*/} # or: name=$(basename "$pathname")
number=${name##*_}
number=${number%.nii}
printf -v newname "%s_%.3d.nii" "${name%_*.nii}" "$number"
printf "Would rename %s --> %s\n" "$pathname" "$dirpath/$newname"
# mv "$pathname" "$dirpath/$newname"
done' bash {} +
Встроенный скрипт bash -c
здесь вызывается find
с пакетами найденных путей, которые удовлетворяют критериям-type f
(является обычным файлом )и-name
(имеет конкретное имя ). Сценарий перебирает эти пути и извлекает имя файла в name
и путь к каталогу в dirpath
.
Затем он выполняет те же операции, что и раньше, чтобы получить новое имя, которое сохраняется в newname
, а затем переименовывает файл.
В целях безопасности я закомментировал реальную команду mv
. Вы должны запустить это один раз, чтобы сначала убедиться, что вывод правильный. Если вы используете инструменты GNU, вы также можете использовать mv -b
для создания резервных копий файлов, если есть конфликты имен.
В качестве примечания: в оболочке zsh
шаблон подстановки
./**/*Vol_*.nii(n)
расширится до всех этих имен в числовом порядке(и рекурсивно вниз по подкаталогам):
$ print -rC1./**/*Vol_*.nii(n)
./swu_run1_P_277_Vol_1.nii
./swu_run1_P_277_Vol_2.nii
./swu_run1_P_277_Vol_10.nii
./swu_run1_P_277_Vol_120.nii