удаление промежуточных папок - PullRequest
0 голосов
/ 01 сентября 2018

Может, у одного из вас, ребята, уже есть что-то подобное? Я пытался использовать robocopy на окнах, но безрезультатно. Я также пытался написать bash-скрипт в linux с find и т. Д ..., но тоже разочаровался в этом ^^ Поиск Google также не принес решения, к сожалению. Мне это нужно для моей личной библиотеки фотографий.

Решение может быть на основе Linux или Windows, оба в порядке. Есть идеи?

Я бы хотел избавиться от сотен «промежуточных папок».

Я определяю «промежуточную папку» как папку, которая содержит только одну подпапку. Пример

folder 1
    file in folder 1
    folder 2            <-- 'intermediary folder: contains exactly one sub-folder, nothing else'
        folder 3
           file in folder 3

То, что я хотел бы закончить, это:

 folder 1
      file in folder 1
      folder 3
           file in folder 3

Мне не нужно, чтобы скрипт был рекурсивным (удаляя сразу несколько слоев промежуточных папок), я просто запускаю его несколько раз.

Еще круче было бы, если бы скрипт мог переименовать папку 3 в вышеприведенном примере в «папка 2 - папка 3», но я могу жить без этой функции, я думаю.

Полагаю, у одного из вас, экспертов по Linux, есть один лайнер для этого? ^^

Большое спасибо!

1 Ответ

0 голосов
/ 01 сентября 2018

Посмотрите на этот код:

#!/usr/bin/env bash

shopt -s nullglob
while IFS= read -rd '' dir; do
    f=("$dir"/*)
    if ((${#f[@]}==1)) && [[ -d $f ]]; then
        mv -t "${dir%/*}" "$f" || continue
        rm -r "$dir"
    fi  
done < <(find folder1 -depth -mindepth 1 -type d -print0)

Пояснение:

  • shopt -s nullglob: позволяет шаблонам имен файлов, которые не соответствуют ни одному файлу, расширяться до пустой строки
  • find ... -depth: заставляет find проходить файловую систему в порядке глубины
  • find ... -mindepth 1: обрабатывает все каталоги, кроме начальной
  • find ... -type d: поиск только каталогов
  • find ... -print0: печать каталогов, разделенных нулевым символом \0 (для правильной обработки возможных новых строк в именах файлов)
  • while IFS= read ...: перебирает все каталоги (вывод find)
  • f=("$dir"/*): создает массив с всеми файлами в текущей обрабатываемой директории
  • ((${#f[@]}==1)) && [[ -d $f ]]: true, если существует только один файл и это каталог
    • mv -t "${dir%/*}" "$f": перемещает единственный подкаталог на один каталог выше
    • mv ... || continue: mv может произойти сбой, если подкаталог уже существует в каталоге выше. || continue игнорирует такой подкаталог
    • rm -r "$dir": удаляет обработанный каталог

Тестовый прогон:

$ tree folder1
folder1
├── file1
├── folder2
│   └── folder3
│       └── file3
├── folder4
│   ├── file4a
│   ├── file4b
│   └── file4c
└── folder5
    └── folder6
        ├── file6
        └── folder7
            └── folder8
                └── folder9
                    ├── dir9
                    └── file9
$ ./script
$ tree folder1
folder1
├── file1
├── folder3
│   └── file3
├── folder4
│   ├── file4a
│   ├── file4b
│   └── file4c
└── folder6
    ├── file6
    └── folder9
        ├── dir9
        └── file9
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...