Копирование отдельных файлов из нескольких каталогов в новый каталог с несколькими подкаталогами, содержащими каждый файл.

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

Я пытаюсь скопировать один конкретный файл, который содержится в 960 подкаталогах родительского каталога. Каждый файл имеет одно и то же имя, но уникальное содержимое.

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

Мне также нужно создать каждый из этих подкаталогов, названных processorN, где N – это число от 0 до 959.

Какие-либо идеи? Это затрудняет меня, и я не могу найти хорошее решение, которое не займет у меня часы.

rsync может сделать это с помощью хитрых флагов --include и --exclude:

rsync -a -v --include="*/" --include="specific-file.txt" --exclude="*" from/ to/

Это скопирует все каталоги и specific-file.txt из from в to, пропуская все остальное. Команда сохранит полную структуру каталогов ниже from и скопирует ее в to. Вы можете сначала запустить это с ключом -n, чтобы увидеть, что произойдет, то есть:

# проверка:
rsync -a -v -n --include="*/" --include="specific-file.txt" --exclude="*" from/ to/

# фактическое выполнение:
rsync -a -v    --include="*/" --include="specific-file.txt" --exclude="*" from/ to/

Я бы просто использовал find и обработал вывод, вот так:

# скопировать все экземпляры имени файла из srcroot в destroot,
# сохраняя структуру каталога
filename="foo.txt"
srcroot="/path/to/src"
destroot="/path/to/dest"

for file in $(find "$srcroot" -name "$filename" -type f -printf "%P\n"); do
    path=$(dirname "$file")
    mkdir -p "$destroot/$path"
    cp -a "$srcroot/$file" "$destroot/$path"
done

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

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

Для копирования конкретного файла из множества подкаталогов и сохранения иерархии каталогов в новой директории, можно использовать утилиту find в сочетании с cp и mkdir. Вот решение, которое полностью соответствует вашим требованиям:

  1. Переменные:
    • Задайте переменные для имени файла, корневой директории источника и директории назначения.
filename="specific-file.txt"  # Укажите имя вашего файла
srcroot="/путь/к/исходной/директории" # Укажите путь к родительскому каталогу с подкаталогами
destroot="/путь/к/целевой/директории" # Укажите путь к новому родительскому каталогу
  1. Команда find:
    Используйте find, чтобы найти все нужные файлы, а затем выполните циклическое копирование:
find "$srcroot" -name "$filename" -type f | while read -r file; do
    # Получаем путь относительно корневой директории sources
    relpath="${file#$srcroot/}"
    # Устанавливаем директорию назначения
    destdir="$destroot/$(dirname "$relpath")"
    # Создаем подкаталог, если он не существует
    mkdir -p "$destdir"
    # Копируем файл в назначенную директорию
    cp "$file" "$destdir/"
done

Объяснение кода:

  • find "$srcroot" -name "$filename" -type f — находит все файлы с заданным именем в указанной директории и её подкаталогах.
  • while read -r file; do ... done — циклически обрабатывает каждый найденный файл.
  • relpath="${file#$srcroot/}" — получает относительный путь для создания соответствующей структуры каталогов в новой директории.
  • destdir="$destroot/$(dirname "$relpath")" — задает путь назначения, включая папку, в которую будет скопирован файл.
  • mkdir -p "$destdir" — создает необходимую директорию, если она ещё не существует.
  • cp "$file" "$destdir/" — выполняет копирование найденного файла в целевую директорию.

Возможное использование:

Это решение эффективно и достаточно простое для понимания. Вы можете легко адаптировать его под дополнительные условия, если это потребуется. Если у вас есть другие вопросы или если вам требуется дополнительная помощь, не стесняйтесь обращаться!

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

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