Рекурсивный поиск и перемещение файловой системы

У меня есть файловая система, которую я хотел бы организовать в алфавитном порядке. Это является большим, и сделать это вручную заняло бы время жизни.

То, что я хотел бы знать, - было ли возможно записать что-то в терминале, который создаст папки A-Z и затем иметь терминал, ищут всю файловую систему и перемещают все подпапки в их соответствующую папку букв.

Я также хотел бы, чтобы поиск организовал основанный на расширении файла, найденном в подпапке.

например, найдите и переместите все подпапки, начинающиеся с буквы содержание расширения файла .doc к folderA.

Заранее спасибо

1
задан 6 February 2017 в 21:44

1 ответ

Можно использовать find команда ниже к рекурсивно перемещению (в глубину) все папки в папку, названную в честь первой буквы их имени файла, создавая его, если это еще не существует, начинающий с Вашего текущего рабочего каталога:

find . -depth -mindepth 1 -type d -execdir bash -c 'l=./$(basename "{}" | head -c1) ; test -d "${l^^}" || mkdir "${l^^}" ; mv "{}" "${l^^}/"' \;

Объяснение:

  • find . -depth -mindepth 1 -type d -execdir <COMMAND> \;
    рекурсивно ищет Ваш текущий каталог (.), в глубину (-depth), для всех каталогов (-type d), исключая Ваш текущий каталог сам (-mindepth 1).
    Затем это cds в родительский каталог каждой найденной папки и выполняется <COMMAND> оттуда, заменяя каждое возникновение {} с родственником нашел имя каталога (-execdir).
  • bash -c '<COMMAND>'
    запускает подоболочку Bash и позволяет ему интерпретировать и выполнить строку <COMMAND>. Нам нужно это, потому что мы собираемся использовать функции оболочки как переменные, каналы, замена команды, и т.д., который не может быть сделан непосредственно find -execdir.
  • l=./$(basename "{}" | head -c1)
    хранит первую букву найденного имени каталога (помните это {} заменен с результатом поиска) в переменной оболочки $l.
  • test -d "${l^^}" || mkdir "${l^^}"
    проверки, существует ли каталог и создает его если нет. Название каталога ("${l^^}") содержание переменной $l (первая буква найденного имени каталога) преобразованный в верхний регистр.

  • mv "{}" "${l^^}/"
    перемещается найденный каталог (помните снова это {} заменен) в каталог, названный после того, как его первая буква преобразовала в верхний регистр ('" $ {l^^} / ", который мы подготовили ранее).

Пример выполняется:

$ tree -F
.
├── apple/
│  ├── hamster/
│  ├── horse/
│  ├── snake/
│  │  ├── blue
│  │  ├── green
│  │  ├── grey
│  │  └── red
│  └── spider/
├── apricot/
├── banana/
├── cherry/
│  ├── pink
│  ├── purple
│  └── yellow
└── coconut/

9 directories, 7 files
$ find . -depth -mindepth 1 -type d -execdir bash -c 'l=./$(basename "{}" | head -c1) ; test -d "${l^^}" || mkdir "${l^^}" ; mv "{}" "${l^^}/"' \;
$ tree -F
.
├── A/
│  ├── apple/
│  │  ├── H/
│  │  │  ├── hamster/
│  │  │  └── horse/
│  │  └── S/
│  │  ├── snake/
│  │  │  ├── blue
│  │  │  ├── green
│  │  │  ├── grey
│  │  │  └── red
│  │  └── spider/
│  └── apricot/
├── B/
│  └── banana/
└── C/
    ├── cherry/
    │  ├── pink
    │  ├── purple
    │  └── yellow
    └── coconut/

14 directories, 7 files

Править:

Если Вы хотите это нерекурсивно, т.е. работа только на прямых подкаталогах первого уровня Вашего текущего рабочего каталога, просто добавьте -maxdepth 1 опция к find команда. Можно опустить -depth опция затем, хотя:

find . -mindepth 1 -maxdepth 1 -type d -execdir bash -c 'l=./$(basename "{}" | head -c1) ; test -d "${l^^}" || mkdir "${l^^}" ; mv "{}" "${l^^}/"' \;

Редактирование 2:

Возможно только выполнить перемещение, если каталог для перемещения содержит файлы, соответствующие определенному критерию (здесь: содержите файл с именем файла, заканчивающимся в .jpg где угодно, включая подкаталоги), но это добавляет другого find команда и if пункт:

find . -depth -mindepth 1 -maxdepth 1 -type d -execdir bash -c 'if find "{}" -type f -iname '*.jpg' | grep -q '.' ; then l=./$(basename "{}" | head -c1) ; test -d "${l^^}" || mkdir "${l^^}" ; mv "{}" "${l^^}/" ; fi' \;

Объяснение (после того, как редактируют 2):

  • if <CONDITION> ; then <COMMANDS> ; fi
    Проверяет код выхода команды <CONDITION> и только выполнения <COMMANDS> между then и fi если условие было выполнено (код выхода 0). <COMMANDS> совпадает с в предыдущей версии.
  • find "{}" -type f -iname '*.jpg' | grep -q '.' Поиски в каталоге найдены внешним find команда (помнят еще раз это {} заменен) файлы (-type f) с именем, которое заканчивается .jpg, нечувствительно к регистру (-iname '*.jpg').
    grep -q '.' просто проверки, ли find производит любой вывод на STDOUT (означает, что файлы были найдены), и возвращает код выхода 0 затем, 1, если никакие файлы не были найдены.

Пример работает (после того, как отредактируйте 2):

$ tree -F
.
├── apple/
│  ├── hamster/
│  ├── horse/
│  ├── snake/
│  │  ├── blue
│  │  ├── green
│  │  ├── grey
│  │  └── red
│  └── spider/
├── apricot/
├── banana/
│  └── black.jpg
├── cherry/
│  ├── pink
│  ├── purple
│  └── yellow
└── coconut/

9 directories, 8 files

$ find . -depth -mindepth 1 -maxdepth 1 -type d -execdir bash -c 'if find "{}" -type f -iname '*.jpg' | grep -q '.' ; then l=./$(basename "{}" | head -c1) ; test -d "${l^^}" || mkdir "${l^^}" ; mv "{}" "${l^^}/" ; fi' \;
$ tree -F
.
├── A/
│  └── apple/
│  ├── hamster/
│  ├── horse/
│  │  └── white.jpg
│  ├── snake/
│  │  ├── blue
│  │  ├── green
│  │  ├── grey
│  │  └── red
│  └── spider/
├── apricot/
├── B/
│  └── banana/
│  └── black.jpg
├── cherry/
│  ├── pink
│  ├── purple
│  └── yellow
└── coconut/

11 directories, 9 files
2
ответ дан 7 December 2019 в 13:37

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

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