使用下划线批量复制并重命名Bash中的多个文件

时间:2017-03-05 15:35:20

标签: bash

所以,我在bash的一个名为songs_old的目录中有几个文件。我想将它们复制到名为带有不同名称的歌曲的文件夹中。输入文件的某些名称包括:

unknownsong_song152.mid
town_song154.mid
nm_battle_song158.mid
fanfare_song159.mid

我希望“歌曲”中的结果如下:

song152_unknownsong.mid
song154_town.mid
song158_nm_battle.mid
song159_fanfare.mid

我尝试使用以下代码来复制文件:

#!/bin/bash
for i in "./songs_old/"*".mid";do mkdir -p "./songs"
  cp "$i" "./songs/`basename "${i%.*}" | cut -d'_' -f2`_`basename "${i%.*}" | cut -d'_' -f1`.mid"
done

我的结果如下:

song152_unknownsong.mid
song154_town.mid
battle_nm.mid
song159_fanfare.mid

如何复制具有所需结果的文件?

2 个答案:

答案 0 :(得分:2)

使用纯bash正则表达式,您可以这样做:

cd songs_old
mkdir -p ../songs

for f in *.mid; do
   [[ $f =~ ^(.+)_([^_]+)(\.[^.]+)$ ]] &&
      cp "$f" ../songs/"${BASH_REMATCH[2]}_${BASH_REMATCH[1]}${BASH_REMATCH[3]}"
done

这将针对给定样本运行以下cp命令:

cp unknownsong_song152.mid ../songs/song152_unknownsong.mid
cp town_song154.mid ../songs/song154_town.mid
cp nm_battle_song158.mid ../songs/song158_nm_battle.mid
cp fanfare_song159.mid ../songs/song159_fanfare.mid

答案 1 :(得分:1)

您的cp命令被传送到cut - 这就是问题所在。你可以这样重写循环:

#!/bin/bash
mkdir -p songs
cd songs_old
for i in *.mid; do
  [[ -f "$i" ]] || continue # make sure we have a file
  new_file=$(sed -E 's/^(.*)_(song[0-9]+).mid$/\2_\1.mid/' <<< "$i")
  echo "Copying $i to $new_file"
  cp "$i" "../songs/$new_file"
done
  • 更有意义的是只创建一次“歌曲”目录
  • 通过cd'ing到songs_old和globbing,我们消除了对basename
  • 的需求
  • 使用sed和正则表达式创建新名称
  • 复制时使用相对路径../songs

对于您的文件集,它会提供以下输出:

Copying fanfare_song159.mid to song159_fanfare.mid
Copying nm_battle_song158.mid to song158_nm_battle.mid
Copying town_song154.mid to song154_town.mid
Copying unknownsong_song152.mid to song152_unknownsong.mid