Как переместить файл рекурсивно на основе размера и структуры

Я хочу переместить файлы размером более 300 Мб из одного дерева каталогов, где каждый файл находится в подпапках

Пример: у меня есть структура каталогов:

dirA/ dirA/file1 dirA/x/ dirA/x/file2 dirA/y/ dirA/y/file3 

Вот ожидаемый результат, «перемещение» дерева каталогов, в котором каждый файл перемещен в подпапки:

 dirB/ # normal directory dirB/file1 # moved from dirA/file1 dirB/x/ # normal directory dirB/x/file2 # moved from dirA/x/file2 dirB/y/ # normal directory dirB/y/file3 # moved from dirA/y/file3 

find /path/ -type f -size +300m но что тогда? и, к сожалению, некоторые из файлов имеют всевозможные символы, которые вы можете найти на своей клавиатуре.

Я смотрел эту тему, где кто-то говорит о cpio но я не знаю, что программа …

PS: У вас установлен GNU Parallel, если это может ускорить работу?

  • Как заставить скрипт работать как демон, ожидая изменений в 2 файлах?
  • Сортировка однозначно из строки
  • Использование tcpdump для регистрации вложенных в черный список IP-адресов
  • Пакетный импорт файлов .sql
  • Запуск скрипта во время загрузки / запуска; init.d vs cron @reboot
  • Как программно контролировать пересылаемые приложения X11?
  • Сортировка вывода awk за исключением первой строки?
  • Замените данные на определенный символ, затем измените значение после x строк
  • 4 Solutions collect form web for “Как переместить файл рекурсивно на основе размера и структуры”

    Легкий способ – с zsh . Вы можете использовать квалификаторы glob для соответствия файлам в соответствии с такими критериями, как их тип и размер. Шаблон подстановки **/ соответствует любому уровню подкаталогов. Модификаторы истории h и t – это простые способы извлечения каталога и базовой части имени файла. Вызовите mkdir -p для создания каталогов по мере необходимости.

     cd dirA for x in **/*(.Lm+300); do mkdir -p ../dirB/$x:h && mv -- $x ../dirB/$x done 

    Портативный способ – find . Используйте -exec для вызова фрагмента оболочки для каждого файла.

     cd dirA find . -type f -size +300000k -exec sh -c 'for x do mkdir -p "../dirB/${x%/*}" mv "$x" "../dirB/$x" done' sh {} + 

    Параллелизация редко используется для ввода / вывода: она позволяет вам использовать преимущества нескольких процессоров, но CPU редко является узким местом в I / O.

    Perl rename – это очевидный выбор. Он может быть установлен как ren , rename или pren :

     find dirA -type f -size +300M | ren 's:^dirA/:dirB/:' 

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

    Параллель с GNU будет медленнее:

     cd dirA find . -type f -size +300M | parallel mkdir -p ../dirB/{//} find . -type f -size +300M | parallel mv {} ../dirB/{} 

    но будет работать, даже если ему нужно выполнить процедуру copy-then-remove, чтобы получить файлы в другую файловую систему.

    Вкратце:

     find dirA -type f -size +300m -printf "mv %p dirB/%P\n" | sh 

    Но все подкаталоги в dirB должны существовать до начала. По этой причине я предлагаю вам выполнить следующие два шага:

     cd dirA find . -type f -size +300m -printf "mkdir -p ../dirB/%h\nmv %p ../dirB/%P\n" | sh 

    Что касается cpio (на самом деле он решает проблему подкаталогов):

     (cd dirA; find . -type f -size +300m) | cpio -p -md dirB 

    (Что касается cp (1) в том же потоке, о котором вы говорите, это не хорошо для вас, потому что он скопирует все файлы и создаст подкаталог с именем dirA под dirB. Флаг -T может решить эту проблему)

    Это должно покрыть его.

     find /path -type f -size +300m | while read A ; do DEST=${A/dirA/dirB} ; echo mkdir -p $(dirname $DEST) 2>/dev/null; echo mv $A $DEST ; done 

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

    В вашем примере структуры файла будут созданы следующие команды

     mkdir -p ./dirB mv ./dirA/file1 ./dirB/file1 mkdir -p ./dirB/x mv ./dirA/x/file2 ./dirB/x/file2 mkdir -p ./dirB/y mv ./dirA/y/file3 ./dirB/y/file3 
    Linux и Unix - лучшая ОС в мире.