删除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 

我不知道为什么它不起作用;我尝试过(从另一篇文章中):

 for file in *.gz;
 do new_name=$(sed 's/_[^.]*_/_g' <<< "new_name");
 mv "$file" "$new_name"; done

重命名/ sed的变体,但没有任何变化。

解决方法

脚本问题至少包括

  • 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
,

你可以做

for i in *_5*.nii.gz *_6*.nii.gz;do a=${i%%_*};b=${i##*_};[[ $i != $a"_"$b ]] && mv $i $a"_"$b;done

编辑后,建议文件可以重命名。

,

Bash的内置字符串替换及其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