Bash: копировать имена файлов рекурсивно, сохраняя структуру папок

Я надеялся:

cp -R src/prog.js images/icon.jpg /tmp/package

даст симметричную структуру в каталоге назначения:

/tmp
|
+-- package
    |
    +-- src
    |   |
    |   +-- prog.js
    |
    +-- images
        |
        +-- icon.jpg

но вместо этого оба файла копируются в /tmp/package. Плоская копия. (Это на OSX).

Есть ли простая функция bash, которую я могу использовать для копирования всех файлов, включая файлы, заданные с помощью подстановочных знаков (например, src/*. js), в их законное место в целевом каталоге. Немного напоминает "для каждого файла, запустите mkdir -p $(dirname "$file"); cp "$file" $(dirname "$file")", но, возможно, одну команду.

Это релевантный поток, который предполагает, что это невозможно. Решение автора не так полезно для меня, потому что я хотел бы просто предоставить список файлов, подстановочный знак или нет, и все они скопированы в каталог назначения. IIRC MS-DOS xcopy делает это, но, похоже, нет эквивалента для cp.

Ответ 1

Вы пытались использовать опцию --parents? Я не знаю, поддерживает ли OS X, но это работает в Linux.

cp --parents src/prog.js images/icon.jpg /tmp/package

Если это не работает в OS X, попробуйте

rsync -R src/prog.js images/icon.jpg /tmp/package

как предложено.

Ответ 2

Один из способов:

tar cf - <files> | (cd /dest; tar xf -)

Ответ 3

В качестве альтернативы, если вы старая школа, используйте cpio:

cd /source;
find . -print | cpio -pvdmB /target

Очевидно, вы можете отфильтровать список файлов в своем сердечном содержимом.

Опция '-p' предназначена для режима "проходной" (в отличие от "-i" для ввода или "-o" для вывода). "-v" является подробным (список файлов по мере их обработки). "-m" сохраняет времена модификации. "-B" означает использование "больших блоков" (где большие блоки составляют 5120 байт вместо 512 байтов); возможно, это не имеет никакого эффекта в наши дни.

Ответ 4

параметр rsync -R будет делать то, что вы ожидаете. Это очень многофункциональный файловый копир. Например:

$ rsync -Rv src/prog.js images/icon.jpg /tmp/package/
images/
images/icon.jpg
src/
src/prog.js

sent 197 bytes  received 76 bytes  546.00 bytes/sec
total size is 0  speedup is 0.00

Примеры результатов:

$ find /tmp/package
/tmp/package
/tmp/package/images
/tmp/package/images/icon.jpg
/tmp/package/src
/tmp/package/src/prog.js

Ответ 6

Try...

for f in src/*.js; do cp $f /tmp/package/$f; done

поэтому за то, что вы делали изначально...

for f in `echo "src/prog.js images/icon.jpg"`; do cp $f /tmp/package/$f; done

или

v="src/prog.js images/icon.jpg"; for f in $v; do cp $f /tmp/package/$f; done