Перемещение, как и именованные файлы, в самоназванные каталоги

У меня есть несколько тысяч файлов в одном каталоге, которые я хотел бы сортировать в таких каталогах:

Из этого:

└── Files
    ├── AAA.mkv
    ├── AAA.nfo
    ├── AAA-picture.jpg
    ├── BBB.mp4
    ├── BBB.srt
    ├── BBB-clip.mp4
    ├── CCC.avi
    ├── CCC.srt
    ├── CCC-clip.mov
    └── CCC.nfo

К этому:

[ f2]

Имена файлов различаются по длине и количеству слов, иногда разделенных пробелами и, возможно, несколькими с дефисами (в дополнение к завершающим «-short». Это в первую очередь видеофайлы с различными форматами / контейнерами : mov / mpg / mkv / mp4 / avi / ogg. Некоторые из них имеют субтитры. Некоторые из них имеют файлы со связанными метаданными (.nfo или -clip)

Редактирование: основными файлами являются видео (здесь я бы например, рисовать имя каталога). Связанные файлы представляют собой метаданные. Некоторые разные имена в именах только с расширением. Есть полдюжины других вариантов базового имени файла, такого как -clip.mp4 -clip.mov или -picture.jpg I если бы что-то предлагалось с этими немногими, то я мог (надеюсь) работать над выяснением остальных. Таким образом, AAA.mkv переходит в каталог с именем AAA. Затем все файлы метаданных, начинающиеся с AAA, присоединяются к нему (т.е. , в этом примере: AAA-picture.jpg и AAA.nfo). Таким образом, базовое имя на самом деле является подстрокой в ​​случае файла AAA-picture.jpg. Я бы сказал, что, вероятно, относительно безопасно просто использовать дефис в качестве разделительного фактора ... хотя «-clip» или «-picture» в целом будет более безопасным.

Как я могу это сделать без получение синдрома кистевого туннеля? Я посмотрел на это, но он был достаточно другим, что мои слабые способности к скриптингу испугались.

Спасибо.

1
задан 13 April 2017 в 15:24

2 ответа

Я сделал небольшой скрипт bash для этого, упрощенного и улучшенного благодаря комментариям OP, @dannysauer, @Arronical и @Scott

#!/bin/bash
for file in *
  do mkdir -p "${file%%[.-]*}" 2>/dev/null
    if [[ -d "${file%%[.-]*}" ]]; then
       if [[ -f "$file" ]]; then
         echo mv -v -- "$file" "${file%%[.-]*}"
       fi
    fi
done

Сначала запустите с echo, а затем удалите [ f4] для фактического перемещения файлов. Сценарий должен запускаться из каталога, в который вы хотите переместить файлы. Если вы предпочитаете, здесь это как однострочная команда:

for file in *; do mkdir -p "${file%%[.-]*}"; if [[ -d "${file%%[.-]*}" ]]; then if [[ -f "$file" ]]; then echo mv -v -- "$file" "${file%%[.-]*}"; fi ; fi ; done

(снова удалите echo после тестирования)

Объяснение:

for file in *; do mkdir -p "${file%%[.-]*}" создать каталог с именем первой части имени каждого файла (до первого символа дефиса или точки). Флаг -p здесь очень важен - без него скрипт будет перемещать только первый соответствующий файл (спасибо Arronical за указание, что -p остановит mkdir попытку создания существующих каталогов и жалуется на это) 2>/dev/null сценарий жалуется, что он не может создать каталог с тем же именем, что и он сам (но все же работает) поэтому мы выбрасываем ошибку - это не требуется при работе как однострочный if [[ -d "${file%%[.-]*}" ]]; then, если есть каталог с таким именем (если mkdir был успешным), тогда ... if [[ -f "$file" ]], если мы имеем дело с файлом (не каталогом или чем-то еще), тогда ... mv -v -- "$file" "${file%%[.-]*}" переместите его в соответствующий каталог.
9
ответ дан 23 May 2018 в 04:13
  • 1
    Чтобы избежать создания каталога для самого скрипта, можно также превратить его в функцию ~/.bashrc;) – Sergiy Kolodyazhnyy 14 November 2016 в 12:33
  • 2
    Вы можете использовать mkdir -p, который не жалуется на уже существующие каталоги. – Arronical 14 November 2016 в 14:32
  • 3
    @Arronical awesome! Спасибо, я редактировал – Zanna 14 November 2016 в 14:45
  • 4
    Некоторые имена файлов имеют пробелы и / или символы подчеркивания. После немного регулярного выражения googling я заменил [: alnum:] на [a-zA-Z0-9 \ _], но потом он, кажется, забирает расширение (включая период?), И я нахожусь в недоумении (поскольку он не может создать каталог с тем же именем, что и файл). – MrFinn 14 November 2016 в 21:15
  • 5
    @dannysauer haha ​​так правдиво, я думаю и не пытаюсь использовать регулярное выражение в оболочке " но на самом деле, никаких оправданий для того, чтобы не думать о классе char. Я отредактировал, и первый тест, вероятно, излишний (и, возможно, бесполезный), но я очень рад, что он работает лучше и не анализирует find. Я должен тебе выпить :) – Zanna 15 November 2016 в 21:17

На маленьком скрипте python:

#!/usr/bin/env python3
import shutil
import os
import sys

dr = sys.argv[1]

for f in os.listdir(dr):
    split = f.rfind("."); short = f.find("-")
    if split != -1:
        extension = f[split:]
        newname = f[:short] if short != -1 else f[:split]
        target = os.path.join(dr, newname)
        if not os.path.exists(target):
            os.mkdir(target)
        shutil.move(os.path.join(dr, f), os.path.join(target, f))

Чтобы использовать его:

скопируйте его в пустой файл. Сохраните его как move_into.py Запустите его с каталогом в качестве аргумента:
python3 /path/to/move_into.py /path/to/directory

Сценарий предполагает, что все (соответствующие) файлы имеют расширения. Если файл не имеет расширения, с ним ничего не происходит.

Объяснение

скопируйте его в пустой файл Если нет, сценарий покидает файл (или каталог). Сохраните его как move_into.py Если нет, базовое имя файла используется для указания папки.

Затем файл перемещается в соответствующую папку.

5
ответ дан 23 May 2018 в 04:13
  • 1
    @Serg, поэтому я использовал rfind, чтобы найти только последнюю точку, отделив расширение. – Jacob Vlijm 14 November 2016 в 10:54
  • 2
    @Serg отредактировал мой ответ. – Jacob Vlijm 14 November 2016 в 11:51

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

Похожие вопросы: