Копирование каталога в подпапки в Linux

Вопрос или проблема

У меня есть папка MAIN с примерно 1200 файлами, оканчивающимися на .bam. Я хочу скопировать эти файлы из MAIN в “/path/to/output/folder”, но в подпапки, содержащие по 50 .bam файлов каждая. Таким образом, я хочу разделить файлы из MAIN на подпапки, каждая из которых содержит 50 файлов. Подпапки не будут находиться в папке MAIN.

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

i=0; 

for f in *; 
do 
    d=dir_$(printf %03d $((i/50+1))); 
    mkdir -p $d; 
    mv "$f" $d; 
    let i++; 
done

Для простого исправления вы можете просто заменить mv на cp, чтобы переключиться с перемещения на копирование, затем добавьте префикс к $d (например, "/path/to/$d").

Тем не менее, есть несколько предостережений относительно этого решения.

Я предполагаю, что вы, вероятно, работаете с “нормальными” именами файлов и папок, но поскольку это не всегда безопасное предположение, я рекомендую ознакомиться с Почему циклический обход выходных данных команды find является плохой практикой?, чтобы узнать надежные способы обхода имен файлов.

Вот одно решение, которое должно правильно обрабатывать произвольные имена файлов:

ORIGIN_DIR="/path/to/origin"
DESTINATION_PARENT_DIR="/path/to/destination"
SHARD_SIZE=50
FIND_BY_NAME="*.bam"

readarray -d '' -t ORIGIN_FILES < <(
  find "$ORIGIN_DIR" -maxdepth 1 -type f -name "$FIND_BY_NAME" -print0
)

for index in "${!ORIGIN_FILES[@]}"; do
  shard_suffix="$(printf %03d $(($index / $SHARD_SIZE + 1)))"
  destination_dir="$DESTINATION_PARENT_DIR/part_$shard_suffix"
  mkdir -p "$destination_dir"
  cp "${ORIGIN_FILES[$index]}" "$destination_dir/"
done

Если вы хотите рекурсивно искать все пути в папке-источнике, а не просто работать с ее прямыми дочерними элементами, вы можете удалить аргумент -maxdepth 1.

Ответ или решение

Копирование директории в подкаталоги на Linux: Подробное руководство

Если у вас есть директория с множеством файлов и вы хотите организовать эти файлы по подкаталогам с определённым ограничением на количество файлов в каждом подкаталоге, вы на правильном пути. В этой статье мы подробным образом рассмотрим, как скопировать файлы из директории MAIN в подкаталог /path/to/output/folder, размещая по 50 файлов в каждом подкаталоге.

Общий алгоритм

  1. Определение путей: Убедитесь, что вы правильно указали исходный и целевой каталоги.
  2. Сбор файлов: Используйте команду find, чтобы собрать все нужные файлы с расширением .bam.
  3. Копирование файлов в подкаталоги: Создайте подкаталоги и размещайте в них файлы в соответствии с заданным количеством.

Пример скрипта

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

#!/bin/bash

# Определяем пути к исходной и целевой директориям
ORIGIN_DIR="/path/to/MAIN"
DESTINATION_PARENT_DIR="/path/to/output/folder"
SHARD_SIZE=50          # Количество файлов в подкаталоге
FIND_BY_NAME="*.bam"   # Шаблон для поиска

# Читаем файлы в массив, учитывая специальные символы
readarray -d '' -t ORIGIN_FILES < <(
  find "$ORIGIN_DIR" -maxdepth 1 -type f -name "$FIND_BY_NAME" -print0
)

# Проходим по каждому файлу и копируем его в соответствующий подкаталог
for index in "${!ORIGIN_FILES[@]}"; do
  shard_suffix="$(printf %03d $((index / SHARD_SIZE + 1)))"  # Счётчик для создания имени подкаталога
  destination_dir="$DESTINATION_PARENT_DIR/part_$shard_suffix"  # Имя подкаталога
  mkdir -p "$destination_dir"  # Создание подкаталога, если его нет
  cp "${ORIGIN_FILES[$index]}" "$destination_dir/"  # Копирование файла
done

Пояснение к скрипту

  1. Настройка переменных:

    • ORIGIN_DIR: Исходная директория, содержащая файлы.
    • DESTINATION_PARENT_DIR: Директория, куда будут скопированы подкаталоги.
    • SHARD_SIZE: Максимальное количество файлов в подкаталоге. Вы установили 50.
    • FIND_BY_NAME: Используется для фильтрации файлов по заданному шаблону.
  2. Сбор файлов:

    • Команда find ищет все файлы с расширением .bam в указанной директории. Опция -print0 позволяет безопасно работать с файлами, содержащими пробелы или другие специальные символы.
  3. Копирование файлов:

    • Цикл проходит по всем найденным файлам. В зависимости от индекса файла создаётся подкаталог с уникальным номером.
    • Команда mkdir -p создаёт подкаталог, если он ещё не существует.
    • Команда cp копирует файлы в соответствующие подкаталоги.

Заключение

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

Если у вас возникнут вопросы или потребуется дальнейшая помощь, не стесняйтесь уточнять!

Оцените материал
Добавить комментарий

Капча загружается...