Как переименовать много файлов, используя информацию из отдельного файла.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/

Другие вопросы по тегам