Як замінити папку з назвою дата, тобто YYYYMMDD, на ієрархію папок року, місяця, дати?


8

У мене є список папок, які мають дати імен. Дати у форматі YYYYMMDD (наприклад, 20150129). У цих папках є текстові документи, які пов'язані з цією конкретною датою.

Я хотів би переструктурувати їх у ієрархії папок, що триває від року до місяця, а також перемістити текстові документи у відповідну папку "дата" нижче вниз в ієрархії.

Іншими словами, я хотів би, щоб папку 'root' було названо так, як рік 2015, а потім створити підпапки з іменем місяця, як 01, а потім створити додаткові підпапки з іменем, як 29, які містять відповідні текстові документи .

Так шлях виглядав би 2015/01/29/file.txtабо 2015>01>29>file.txt.

Я поглянув на Automator і, здається, щось подібне неможливо, хоча я можу помилитися, тому хотів би знати ...

  1. Чи є якесь просте рішення цієї проблеми, яке може зрозуміти будь-який мирянин, наприклад, робочий процес Automator, або для цього потрібне певне розуміння команд терміналів та регулярних виразів?

  2. Як можна вирішити цю проблему за умови, що насправді є рішення?


Чому хто проголосував, щоб закрити це питання як "занадто широке", чому? Мені цікаво, що "занадто широке" в цьому питанні?
користувач3439894

Ці папки YYYYMMDD є все безпосередньо в одній головній папці чи вони розповсюджені в більш широкій ієрархії?
nohillside

@patrix У моєму випадку вони всі в одному каталозі чи
головній

Відповіді:


8

Якщо припустити, що всі ці папки YYYYMMDD є частиною того самого батьківського каталогу, який ви могли запускати

cd PARENT_DIRECTORY
for d in */; do
    [[ $d =~ [0-9]{8}/ ]] || continue
    mkdir -p -- "${d:0:4}/${d:4:2}"
    mv -- "$d" "${d:0:4}/${d:4:2}/${d:6:2}"
done
  • for d in */; doЦикл зчитує всі записи каталогу, то замикають /гарантують , що тільки імена каталогів фактично збігаються
  • [[ $d =~ [0-9]{8}/ ]] перевіряє, чи складається поточний запис з 8 цифр, і продовжує наступний запис, якщо ні
  • ${d:0:4}/${d:4:2}/${d:6:2}використовує розширення параметрів усередині, bashщоб створити рядок, що містить новий шлях
  • І те, і --інше запобігає проблемі у випадку, якщо ім'я каталогу чи файлу починається з . Це не може відбутися тут, але це, мабуть, добра практика.mkdirmv-

Дякуємо @terdon та @ user3439894 за ідеї, як покращити оригінальний сценарій.


Дякую за відповідь, це прекрасно працює! Я вважаю, що це рішення краще, ніж рішення, яке надає @grgarside, оскільки воно набагато швидше, особливо коли йдеться про масивний корпус, що включає тисячі текстових документів.
davidjnatarajan

8

Ви можете використовувати наступне в Терміналі. cdдо папки, що містить, а потім запустіть наступне:

find . -type f -exec bash -c \
  'F=$(sed -E "s#^\./([0-9]{4})([0-9]{2})([0-9]{2})#\1/\2/\3#" <<< $1);\
  mkdir -p -- $(dirname "$F");\
  mv -- "$1" "$F"' - {} \;

find . -type fотримує кожен файл у поточному каталозі рекурсивно.
-exec bash -cвідкриває оболонку для запуску наступних команд.
F=$(…)відкриває нижню частину і використовує sed на шляху до файлу, щоб маніпулювати шляхом до папок.
^\./([0-9]{4})([0-9]{2})([0-9]{2})являє собою регулярний вираз з трьома групами захоплення наступним чином: це заміна, де кожна група захоплення ( тощо) відокремлена . створює каталоги для переміщення файлів у. переміщує кожен файл у відповідну папку.
\1/\2/\3\1/
mkdir -p -- $(dirname "$F")
mv -- "$1" "$F"

Це приймає ієрархію зліва і перетворює її в ієрархію праворуч:

├── 20170201               └── 2017
   └── abcdefghij             ├── 02
└── 20170302                      └── 01
    └── abcdefghij 2                  └── abcdefghij
                               └── 03
                                   └── 02
                                       └── abcdefghij 2

Якщо в папці, що містить назву, є інші файли з датою як ім'я, вони будуть переміщені так, ніби вони є папкою. Щоб запобігти цьому, замініть другий рядок на:

  'F=$(sed -E "s#^\./([0-9]{4})([0-9]{2})([0-9]{2})(?:/.+)#\1/\2/\3#" <<< $1);\

У (?:/.+)гарантує , що шлях має наступний компонент, тому ігнорування що - або без дитини в батьківському каталозі , які є файлами.


@klanomath regex101.com
grg

@grgarside Thanx
klanomath
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.