我相信这个问题可以通过 bash 脚本解决,但我还是个初学者,所以我需要你的帮助。
我有许多文件(约 800 万个!),其名称如IR.AZR..SHE.D.2016.001.000000.SAC
。文件名遵循以下格式:
IR.(stations name)..(component).D.(year).(day).000000.sac
它们都需要重命名为以下格式:
(station name).IR.(component).(year).(day).(begin time).(endtime).sac
注意:(day)
是 365 格式,或者我应该说是儒略日格式。
当前文件名以及新格式所需的附加信息存储在纯文本文件中:
除了屏幕截图之外,这里是文件的一部分:
IR.AZR..SHE.D.2016.158.071819.SAC 2016 158 7 18 19 300 0.0000 8.2000
IR.AZR..SHE.D.2016.158.072153.SAC 2016 158 7 21 53 540 0.0000 8.2000
IR.AZR..SHE.D.2016.158.072251.SAC 2016 158 7 22 51 60 0.0000 8.1000
IR.AZR..SHE.D.2016.158.072315.SAC 2016 158 7 23 15 580 0.0000 16.3000
IR.AZR..SHE.D.2016.158.072340.SAC 2016 158 7 23 40 180 0.0000 8.2000
IR.AZR..SHE.D.2016.158.072421.SAC 2016 158 7 24 21 300 0.0000 8.1000
IR.AZR..SHE.D.2016.158.072445.SAC 2016 158 7 24 45 980 0.0000 8.2000
IR.AZR..SHE.D.2016.158.072518.SAC 2016 158 7 25 18 60 0.0000 7.3000
IR.AZR..SHE.D.2016.158.072541.SAC 2016 158 7 25 41 620 0.0000 32.9000
IR.AZR..SHE.D.2016.158.072647.SAC 2016 158 7 26 47 540 0.0000 16.4000
IR.AZR..SHE.D.2016.158.072712.SAC 2016 158 7 27 12 260 0.0000 8.1000
IR.AZR..SHE.D.2016.158.072736.SAC 2016 158 7 27 36 860 0.0000 8.2000
IR.AZR..SHE.D.2016.158.072753.SAC 2016 158 7 27 53 340 0.0000 8.2000
IR.AZR..SHE.D.2016.158.072809.SAC 2016 158 7 28 9 820 0.0000 8.1000
IR.AZR..SHE.D.2016.158.072904.SAC 2016 158 7 29 4 740 0.0000 8.2000
IR.AZR..SHE.D.2016.158.072921.SAC 2016 158 7 29 21 220 0.0000 8.2000
IR.AZR..SHE.D.2016.158.072954.SAC 2016 158 7 29 54 60 0.0000 8.2000
IR.AZR..SHE.D.2016.158.073035.SAC 2016 158 7 30 35 260 0.0000 8.1000
IR.AZR..SHE.D.2016.158.073059.SAC 2016 158 7 30 59 940 0.0000 8.2000
- 这第一的列是我的文件列表,其中包含其当前文件名。
- 这第二该列代表的是
(year)
。 - 这第三采用
(day)
儒略日格式。 - 这第八和第九列分别为
(begin time)
和(end time)
。
简而言之,该脚本应该执行以下操作:
先列出所有文件然后找到这个
.txt
文件里面的文件和对应的行和列然后按照我上面说的重命名。
答案1
您的要求可以通过 Perl 单行命令轻松完成:
perl -lane '@a=split/\./,$F[0]; rename "old/$F[0]","new/$a[1].IR.$a[3].$F[1].$F[2].$F[7].$F[8].sac"' input.txt
然而,您的新格式命名方案似乎不适合您的输入文件,因为它会创建重复的名称。例如:
IR.AZR..SHE.D.2016.158.071819.SAC 2016 158 7 18 19 300 0.0000 8.2000
IR.AZR..SHE.D.2016.158.072153.SAC 2016 158 7 21 53 540 0.0000 8.2000
都将转换为:AZR.IR.SHE.2016.158.0.0000.8.2000.sac
。显然,任何时间都只能有一个具有给定文件名的文件,其中一个将会丢失。
请考虑重复项,重新考虑输出文件名格式。一种可能的替代方案可能是:
perl -lane '@a=split/\./,$F[0]; rename "old/$F[0]","new/$a[1].IR.$a[3].$F[1].$F[2].$a[7].$F[7].$F[8].sac"' input.txt
测试运行
初始文件结构:
old:
IR.AZR..SHE.D.2016.158.071819.SAC
IR.AZR..SHE.D.2016.158.072153.SAC
IR.AZR..SHE.D.2016.158.072251.SAC
IR.AZR..SHE.D.2016.158.072315.SAC
IR.AZR..SHE.D.2016.158.072340.SAC
IR.AZR..SHE.D.2016.158.072421.SAC
IR.AZR..SHE.D.2016.158.072445.SAC
IR.AZR..SHE.D.2016.158.072518.SAC
IR.AZR..SHE.D.2016.158.072541.SAC
IR.AZR..SHE.D.2016.158.072647.SAC
IR.AZR..SHE.D.2016.158.072712.SAC
IR.AZR..SHE.D.2016.158.072736.SAC
IR.AZR..SHE.D.2016.158.072753.SAC
IR.AZR..SHE.D.2016.158.072809.SAC
IR.AZR..SHE.D.2016.158.072904.SAC
IR.AZR..SHE.D.2016.158.072921.SAC
IR.AZR..SHE.D.2016.158.072954.SAC
IR.AZR..SHE.D.2016.158.073035.SAC
IR.AZR..SHE.D.2016.158.073059.SAC
new:
使用 OP 的原始格式进行测试运行:
old:
new:
AZR.IR.SHE.2016.158.0.0000.16.3000.sac
AZR.IR.SHE.2016.158.0.0000.16.4000.sac
AZR.IR.SHE.2016.158.0.0000.32.9000.sac
AZR.IR.SHE.2016.158.0.0000.7.3000.sac
AZR.IR.SHE.2016.158.0.0000.8.1000.sac
AZR.IR.SHE.2016.158.0.0000.8.2000.sac
使用改变的输出格式进行测试运行:
old:
new:
AZR.IR.SHE.2016.158.071819.0.0000.8.2000.sac
AZR.IR.SHE.2016.158.072153.0.0000.8.2000.sac
AZR.IR.SHE.2016.158.072251.0.0000.8.1000.sac
AZR.IR.SHE.2016.158.072315.0.0000.16.3000.sac
AZR.IR.SHE.2016.158.072340.0.0000.8.2000.sac
AZR.IR.SHE.2016.158.072421.0.0000.8.1000.sac
AZR.IR.SHE.2016.158.072445.0.0000.8.2000.sac
AZR.IR.SHE.2016.158.072518.0.0000.7.3000.sac
AZR.IR.SHE.2016.158.072541.0.0000.32.9000.sac
AZR.IR.SHE.2016.158.072647.0.0000.16.4000.sac
AZR.IR.SHE.2016.158.072712.0.0000.8.1000.sac
AZR.IR.SHE.2016.158.072736.0.0000.8.2000.sac
AZR.IR.SHE.2016.158.072753.0.0000.8.2000.sac
AZR.IR.SHE.2016.158.072809.0.0000.8.1000.sac
AZR.IR.SHE.2016.158.072904.0.0000.8.2000.sac
AZR.IR.SHE.2016.158.072921.0.0000.8.2000.sac
AZR.IR.SHE.2016.158.072954.0.0000.8.2000.sac
AZR.IR.SHE.2016.158.073035.0.0000.8.1000.sac
AZR.IR.SHE.2016.158.073059.0.0000.8.2000.sac
答案2
纯 Bash +mv(1)
while read -r current year day d e f g begin end; do
station="${current:3:3}" component="${current:8:3}"
mv -T -- "$current" "${station}.IR.${component}.${year}.${day}.${begin}.${end}.sac"
done < file-name-data.txt
mv
尽管有 800 万个文件,但每个文件的执行速度都会很慢。因此我推荐以下替代方案。
Python 3
单行代码(无错误处理)
python3 -c 'import sys, os, re; for m in map(re.compile(sys.argv[1]).match, sys.stdin): os.rename(m.group("current"), sys.argv[2].format_map(m.groupdict()))' '(?P<current>IR\.(?P<station>\S+?)\.\.(?P<component>\S+?)\.\S*)\s+(?P<year>\S+)\s+(?P<day>\S+)\s+(?:\S+\s+){4}(?P<begin>\S+)\s+(?P<end>\S+)' '{station}.IR.{component}.{year}.{day}.{begin}.{end}.sac' < file-name-data.txt
完整程序(带错误处理)
#!/usr/bin/python3
import sys, os, re
src_pattern = re.compile(
r'(?P<current>IR\.(?P<station>\S+?)\.\.(?P<component>\S+?)\.\S*)\s+'
r'(?P<year>\S+)\s+(?P<day>\S+)\s+'
r'(?:\S+\s+){4}'
r'(?P<begin>\S+)\s+(?P<end>\S+)'
)
dst_format = '{station}.IR.{component}.{year}.{day}.{begin}.{end}.sac'
for i, line in enumerate(sys.stdin, 1):
m = src_pattern.match(line)
if m:
try:
os.rename(m.group('current'), dst_format.format_map(m.groupdict()))
except OSError as ex:
print(ex, file=sys.stderr)
else:
print(
'Non-matching source line {:d}: {!r}'.format(i, line.rstrip('\r\n')),
file=sys.stderr)
用法:
python3 rename.py < file-name-data.txt
答案3
有一个命令行工具,multiple move。它允许您根据模式移动(也就是重命名)、复制等。使用以下命令安装它:
sudo apt install mmv
在终端窗口中。然后运行“man mmv”查看手册页,或者查看此处: https://www.systutorials.com/docs/linux/man/1-mmv/
这可能有点令人畏惧,因为问题并不简单。总是首先在数据副本上进行测试。
还有一个图形工具 filebot。它用 Java 编写,可在 Ubuntu 上运行。只需在 Ubuntu 软件商店中搜索它或使用以下命令安装
sudo apt install filebot
它的主要目标是批量重命名视频和音乐文件,并且可以使用 MusicBrainz 等的数据库信息,但如果我没记错的话(但请自己检查一下,因为这个周末我没怎么睡觉 :) )也适用于非媒体文件集。他们的网站在这里: https://www.filebot.net/