копирование нескольких файлов в несколько каталогов

копирование нескольких файлов в несколько каталогов

У меня проблема с копированием многих файлов в разные каталоги. Позвольте мне объяснить лучше:

Допустим, у меня в каталоге есть следующее:

$ ls
file1 file2 file3 file4 file5 dir1 dir2 dir3

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

 echo dir{1..3} | xargs cp file{1..5} '{}' \;

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

решение1

echo dir[1-3] | xargs -r -n1 cp file[1-5]

решение2

Вы делаете небольшую ошибку в использовании xargs. Без параметра -n xargs добавляет все параметры во входных данных к команде и echo dir{1..3}не добавляет необходимый возврат каретки между каждой записью, поэтому xargs будет рассматривать результат как один параметр.

У xargs есть опция -n, которая может ограничить количество записей, и вам необходимо перечислить каталоги с \n или \0 в качестве разделителя:

find . -mindepth 1 -maxdepth 1 -type d -print0 | xargs -0 -n 1 cp file{1..5}

Команда find будет искать все каталоги в текущем каталоге и использовать \0 в качестве разделителя (что работает лучше, если у вас есть каталоги с пробелами), а xargs использует \0 в качестве разделителя и запускает команду каждый раз только с одним параметром.

решение3

Что-то вроде следующего должно сработать, если у них действительно есть такие имена:

#!/bin/bash
shopt -s nullglob
for dir in dir*/; do
    cp file* "$dir"
done

Если вы хотите скопировать все файлы во все каталоги независимо от имени:

#!/bin/bash
shopt -s nullglob dotglob
for dir in */; do
    for file in *; do
        [[ -f $file ]] && cp "$file" "$dir"
    done
done

решение4

Вы почти у цели. Вам нужно запустить отдельную cpкоманду для каждого целевого каталога, потому что cpсоздает только одну копию каждого исходного файла. Основная цель xargs— запустить одну команду для нескольких аргументов, но вы можете указать ей передавать по одному элементу за раз с помощью параметра -n. Также {} ;есть синтаксис find … -exec; вам не нужно (и вы не можете использовать) его с xargs.

echo dir{1..3} | xargs -n 1 cp file{1..5}

Обратите внимание, что это работает только в том случае, если имена ваших каталогов не содержат пробелов или любых символов \'", поскольку xargsнет способа определить, что эти символы являются частью имен файлов, а не кавычками и разделителями входных файлов. Альтернативный метод, не имеющий таких проблем, — использовать цикл оболочки:

for d in dirs{1..3}; do
  cp file{1..5} "$d"
done

Все это предполагает, что вы можете легко различать файлы и каталоги по их именам. Если вы не можете, вы можете сопоставить каталоги, добавив /в конце; например, */сопоставляет все каталоги в текущих каталогах, foo[0-9]*/сопоставляет все каталоги, имя которых начинается с fooи цифры и т. д. В большинстве оболочек нет похожего способа сопоставить только некаталоги, но если вы передаете каталоги без cpаргумента, чтобы указать ему сделать рекурсивную копию, каталоги игнорируются с сообщением об ошибке.

for d in */; do
  cp * "$d"
done

В zsh вы можете использоватьквалификаторы globдля сопоставления только определенных типов файлов.

for d in *(/); do
  cp *(.) $d
done

Связанный контент