删除 bash 中的中间名称
Remove middle of name in bash
我有 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
我不明白为什么它不起作用;我试过了(来自另一个post):
for file in *.gz;
do new_name=$(sed 's/_[^.]*_/_g' <<< "new_name");
mv "$file" "$new_name"; done
和 rename/sed 的变体,但没有任何变化。
你可以
for i in *_5*.nii.gz *_6*.nii.gz;do a=${i%%_*};b=${i##*_};[[ $i != $a"_"$b ]] && mv $i $a"_"$b;done
已根据建议对文件进行重命名进行编辑。
您的脚本问题至少包括
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
Bash的built-in字符串替换及其extglob
选项简化了中间部分的替换:
#!/usr/bin/env bash
shopt -s extglob
for file in T1_*.nii.gz; do
echo mv -- "$file" "${file/_+([^.])_/_}"
done
删除 echo
或将输出通过管道传输到 shell,如果它符合您的期望。
这是我自己测试的输出:
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
我有 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
我不明白为什么它不起作用;我试过了(来自另一个post):
for file in *.gz;
do new_name=$(sed 's/_[^.]*_/_g' <<< "new_name");
mv "$file" "$new_name"; done
和 rename/sed 的变体,但没有任何变化。
你可以
for i in *_5*.nii.gz *_6*.nii.gz;do a=${i%%_*};b=${i##*_};[[ $i != $a"_"$b ]] && mv $i $a"_"$b;done
已根据建议对文件进行重命名进行编辑。
您的脚本问题至少包括
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
Bash的built-in字符串替换及其extglob
选项简化了中间部分的替换:
#!/usr/bin/env bash
shopt -s extglob
for file in T1_*.nii.gz; do
echo mv -- "$file" "${file/_+([^.])_/_}"
done
删除 echo
或将输出通过管道传输到 shell,如果它符合您的期望。
这是我自己测试的输出:
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