Как переименовать много файлов, используя информацию из отдельного файла.txt?
Я считаю, что эту проблему можно решить с помощью bash-скрипта, но я все еще новичок, поэтому мне нужна ваша помощь здесь.
У меня есть много файлов (около 8 миллионов!) С такими именами, как 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файл и соответствующие строки и столбцы и переименуйте, как я уже сказал выше.
3 ответа
Чистый Баш + 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
Хотя с 8 миллионами файлов это будет довольно медленно выполняться mv для каждого из них. Следовательно, почему я рекомендую альтернативу ниже.
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
То, что вы спрашиваете, может быть легко выполнено с помощью однострочного 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
Есть инструмент командной строки, несколько ходов. Он позволяет вам перемещаться (что также является переименованием), копировать и т. Д. На основе шаблонов. Установите его с
sudo apt install mmv
в окне терминала. Затем запустите "man mmv", чтобы увидеть страницу руководства, или посмотрите здесь: https://www.systutorials.com/docs/linux/man/1-mmv/
Это может быть немного сложно, потому что проблема не простая. Всегда сначала проверяйте копию ваших данных.
Существует также графический инструмент, filebot. Он написан на Java и работает на Ubuntu. Просто найдите его в магазине Ubuntu Software или установите с
sudo apt install filebot
Его основной целью является массовое переименование видео и музыкальных файлов, и он может использовать информацию базы данных из MusicBrainz и т. Д., Но если я правильно помню (но проверьте это самостоятельно, пожалуйста, потому что я не спал много в эти выходные:)), также работает хорошо для не медиафайлов. Их сайт находится здесь: https://www.filebot.net/
