#bash #shell #rename #mv
#bash #оболочка #переименовать #mv
Вопрос:
У меня более 300 файлов с именами:
T1_0000106_FS1_MAX_5743.nii.gz T1_0000214_FS1_MAX_5475.nii.gz
T1_0000107_FS1_MAX_5477.nii.gz T1_0000215_FS1_MAX_6162.nii.gz
Я хотел бы удалить все между T1 и _5/6 *.nii.gz итак:
T1_5743.nii.gz T1_5475.nii.gz
T1_5477.nii.gz T1_6162.nii.gz
Я не могу понять, почему это не работает; Я пробовал (из другого сообщения):
for file in *.gz;
do new_name=$(sed 's/_[^.]*_/_g' <<< "new_name");
mv "$file" "$new_name"; done
и варианты переименования / sed, но ничего не меняется.
Комментарии:
1. Конечно, вы получаете сообщения об ошибках от обоих
sed
иmv
при запуске этого скрипта. Подумайте о том, чтобы обратить внимание на то, что они говорят.2. Я предлагаю использовать отдельную
rename
команду Perl.
Ответ №1:
Проблемы с вашим скриптом включают, по крайней мере,
-
s/_[^.]*_/_g
недопустимаяsed
команда. Похоже, вы хотитеs/_[^.]*_/_/g
, или в данном случае,s/_[^.]*_/_/
тоже все будет хорошо. -
<<< "new_name"
перенаправляет строку литералаnew_name
вsed
. Возможно, вы имеете в виду<<< "$new_name"
Лично я бы не стал беспокоиться sed
об этой работе, особенно если у вас большое количество файлов. Bash вполне способен сам выполнять довольно сложные манипуляции со строками, и ваши потребности не требуют от него слишком больших усилий. Рассмотрим:
for f in *.gz; do
# The value of $f with the longest trailing match to _* removed
head=${f%%_*}
# The value of $f with the longest leading match to *_ removed
tail=${f##*_}
new_name="${head}_${tail}"
# Sanity check and avoid needless errors
if [ "$f" != "$new_name" ]; then
mv "$f" "$new_name"
fi
done
Ответ №2:
Вы могли бы сделать
for i in *_5*.nii.gz *_6*.nii.gz;do a=${i%%_*};b=${i##*_};[[ $i != $a"_"$b ]] amp;amp; mv $i $a"_"$b;done
Отредактировано следующее предположение, что файл уже может быть переименован.
Ответ №3:
Встроенная подстановка строк в Bash и ее extglob
опция упрощают замену средней части:
#!/usr/bin/env bash
shopt -s extglob
for file in T1_*.nii.gz; do
echo mv -- "$file" "${file/_ ([^.])_/_}"
done
Удалите echo
или передайте выходные данные в оболочку, если они соответствуют вашим ожиданиям.
Вот результат моего собственного теста:
mv -- T1_0000106_FS1_MAX_5743.nii.gz T1_5743.nii.gz
mv -- T1_0000107_FS1_MAX_5477.nii.gz T1_5477.nii.gz
mv -- T1_0000214_FS1_MAX_5475.nii.gz T1_5475.nii.gz
mv -- T1_0000215_FS1_MAX_6162.nii.gz T1_6162.nii.gz