переименовать файлы в Linux согласно заданным именам в txt-файле используя скрипт

В папке /home/user/Downloads/videos/ расположены скачанные файлы, и из-за того что имена файлов именуются как 000.mp4 при их скачивании, система дописывает нумерацию перед расширением файла - 000.556.mp4.

Также имеется исходная нумерация файла полученная из ссылки на файл на сервере, и информация на уже переименованный файл в файловой системе у меня на ПК, хранится в файле /home/user/Downloads/downloads.txt

downloads.txt внутри, здесь представлена информация только о 3 файлах:

Name: 000.557.mp4
Folder: /home/user/Downloads/videos
URI: http://example.com/videos/2004/000.mp4
Message: Resumable

Name: 000.556.mp4
Folder: /home/user/Downloads/videos
URI: http://example.com/videos/1979/000.mp4
Message: Resumable

Name: 000.555.mp4
Folder: /home/user/Downloads/videos
URI: http://example.com/videos/1977/000.mp4
Message: Resumable

где:

исходное название:

URI: http://example.com/videos/2004/000.mp4

переименованное у меня в системе:

Name: 000.557.mp4

Нужно запустить скрипт с командной строки, который прочитает информацию с файла downloads.txt и переименует все файлы в папке ...videos/ в исходную нумерацию (как файлы хранятся на сервере).

000.557.mp4     ===>    2004.mp4
000.556.mp4     ===>    1979.mp4
000.555.mp4     ===>    1977.mp4

то есть нужно использовать нумерацию, из исходной ссылки, которая указана после example.com/videos/ и перед /000.mp4

Подскажите, пожалуйста, как будет выглядеть такой скрипт, чтобы он смог обработать файлы из папки проставив соответствующую нумерацию для каждого файла, понимая что информация на каждый файл разделена переходом на новую строку!?


Ответы (2 шт):

Автор решения: user207200

Примерно вот так, без обработки всяких исключительных ситуаций.

import re
import pathlib

vdir = pathlib.Path("/home/user/Downloads/videos/")

with open("/home/user/Downloads/downloads.txt") as f:
    for l in f:
        for fname in re.findall("Name: (000.\d+.mp4)", l):
            while True:
                url = re.findall("URI: http://example.com/videos/(\d+)/000(.mp4)", next(f))
                if url:
                    break
            try:
                (vdir / fname).rename(vdir / ''.join(*url))
            except FileNotFoundError:
                print(f'{fname} not found')
→ Ссылка
Автор решения: Pak Uula

Структурированный файл хорошо парсится awk. Для вашего случая подходит вот такая программа:

/Name:/ { name = $2 } # берет имя файла из второго слова в строке, содержащей 'Name:'
/URI:/ { # обрабатывает строку, содержащую 'URI:'
    # извлекает /1977/ и сохраняет в массив arr
    # arr[0] содержит /1977/, arr[1] - 1977
    match($2, /\/([0-9]+)\//, arr); 
    printf "mv %s %s.mp4;\n", name, arr[1]; 
}

На выходе генерирует скрипт для шелла

mv 000.557.mp4 2004.mp4;
mv 000.556.mp4 1979.mp4;
mv 000.555.mp4 1977.mp4;

Можно вытянуть в одну строку:

gawk -e '/Name:/{name=$2};/URI:/{ match($2,/\/([0-9]+)\//, arr); printf "mv %s %s.mp4;\n",name,arr[1]}' some.txt | /bin/sh -s

UPDATE

скрипт rename.sh

#!/bin/bash

txt_file=$1

if [ -z "$txt_file" ]; then
    echo "$0 TEXT_FILE" > /dev/stderr
    exit 1
fi

function mk_script {
    gawk \
        -e '/Name:/{name=$2};/URI:/{ match($2,/\/([0-9]+)\//, arr); printf "mv -- \"%s\" \"%s.mp4\";\n",name,arr[1]}' \
        $txt_file
}

mk_script $1 | sh -s

Этот скрипт вызывается так rename.sh <text-file>

Небольшое изменение в AWK: теперь имена файлов при переименовании оборачиваются в кавычки и после mv добавлена опция --, которая означает, что после этого места знак - не будет интепретироваться как опции.

→ Ссылка