Скопируйте структуру папок (без файлов) из одного места в другое


96

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

Я хочу скопировать в систему Linux, и наш файловый сервер смонтирован там CIFS.



Решение rsync из приведенного выше комментария выглядит аккуратнее.
YE

Ответы:


159

Вы можете сделать что-то вроде:

find . -type d > dirs.txt

создать список каталогов, затем

xargs mkdir -p < dirs.txt

для создания каталогов в месте назначения.


8
Эти решения не будут работать, если в именах каталогов есть пробелы.
Jealie

32
@Jealie Измените команды на find . -type d -print0 >dirs.txtи xargs -0 mkdir -p <dirs.txt. Это заставит обе команды использовать нули в качестве разделителей вместо пробелов.
user1207177 03

3
xargsможет превышать максимальную длину команды системы, когда вы начинаете работать с сотнями или тысячами заказов, поэтому используйте это с осторожностью. (Найдите предел длины команды с помощью getconf ARG_MAX.) При большом количестве каталогов вам, возможно, придется вместо этого написать сценарий для циклического просмотра вывода.
palswim

1
А как насчет разрешений и атрибутов он будет сохранен ??
Ашиш Карпе

3
@TrevorBoydSmith: Спасибо за ваш комментарий. В исходном вопросе ничего не говорилось о необходимости сохранять разрешения, права собственности или атрибуты. Как вы упомянули, для этого потребуется другое решение, но приведенного выше достаточно, чтобы ответить на поставленный вопрос.
Грег Хьюгилл 01

80
cd /path/to/directories &&
find . -type d -exec mkdir -p -- /path/to/backup/{} \;

3
Лучший ответ от меня с находкой. В противном случае вы можете попробовать rsyncрешение от Чена Леви, ответившего на этот вопрос SO
Mat M

3
Что дает опция - mkdir?
Bruce_Warrior 08

10
--- это терминатор опции стандартной утилиты GNU. Это означает «эй, mkdir, любой аргумент после этого, это не флаг, поэтому рассматривайте его как аргумент файла, даже если он начинается с символа '-'».
amphetamachine

4
этот ответ также не сохраняет разрешения и атрибуты каталога . Используйте rynsc для сохранения разрешений и атрибутов
Тревор Бойд Смит,

36

Вот простое решение с использованием rsync:

rsync -av -f"+ */" -f"- *" "$source" "$target"
  • одна линия
  • нет проблем с пробелами
  • сохранить разрешения

Я нашел это решение там


11
то же самое, но более читабельноеrsync -a --include '*/' --exclude '*' "$source" "$target"
Sylvain

1
Проблема с этим решением: мои папки содержат тысячи файлов, а rsync требует времени, чтобы синхронизировать десяток папок.
Christopher K.

6

Я не знаю, ищете ли вы решение для Linux. Если да, вы можете попробовать это:

$ mkdir destdir
$ cd sourcedir
$ find . -type d | cpio -pdvm destdir

cpio, похоже, у меня не работает, по крайней мере, с указанными вами параметрами.
r00fus 08

@ r00fus - пожалуйста , прочтите руководство по CPIO или обратитесь gnu.org/software/cpio
zerodin

6

Это скопирует атрибуты каталогов и файлов, но не данные файлов:

cp -R --attributes-only SOURCE DEST

Затем вы можете удалить атрибуты файлов, если они вам не интересны:

find DEST -type f -exec rm {} \;

1
Было бы отлично, но вы забыли упомянуть о сохранении прав собственности, отметки времени и разрешений. Таким образом, это вызвало беспорядок в Win7 / cygwin - пользователь NULL_SID, неправильный порядок разрешений, не может редактировать разрешения и т.д. и не может получить доступ к созданной файловой структуре.
WebComer

1
Я думаю, что виноват тот, кто пытается использовать Windows для реальной работы.
Tripleee

cp -R --attributes-only --preserve = all --parents -v ИСТОЧНИК DEST
Габор

2

Следующее решение хорошо работало для меня в различных средах:

sourceDir="some/directory"
targetDir="any/other/directory"

find "$sourceDir" -type d | sed -e "s?$sourceDir?$targetDir?" | xargs mkdir -p

2

Это работает:

find ./<SOURCE_DIR>/ -type d | sed 's/\.\/<SOURCE_DIR>//g' | xargs -I {} mkdir -p <DEST_DIR>"/{}"

Просто замените SOURCE_DIR и DEST_DIR.


2

Это решает даже проблему с пробелами:

В исходном / исходном каталоге:

find . -type d -exec echo "'{}'" \; > dirs2.txt

затем воссоздайте его во вновь созданном каталоге:

mkdir -p <../<SOURCEDIR>/dirs2.txt

1

Замените target_dirи source_dirсоответствующими значениями:

cd target_dir && (cd source_dir; find . -type d ! -name .) | xargs -i mkdir -p "{}"

Проверено на OSX + Ubuntu.


0

Скрипт python от Сергея Колодяжного размещен на Копировать только папки, а не файлы? :

#!/usr/bin/env python
import os,sys
dirs=[ r for r,s,f in os.walk(".") if r != "."]
for i in dirs:
    os.makedirs(os.path.join(sys.argv[1],i)) 

или из оболочки:

python -c 'import os,sys;dirs=[ r for r,s,f in os.walk(".") if r != "."];[os.makedirs(os.path.join(sys.argv[1],i)) for i in dirs]' ~/new_destination

К вашему сведению:


0

Другой подход - использовать treeдовольно удобный и перемещаться по деревьям каталогов на основе его сильных опций. Есть параметры только для каталога, исключить пустые каталоги, исключить имена с шаблоном, включить только имена с шаблоном и т.д.man tree

Преимущество : вы можете редактировать или просматривать список, или, если вы выполняете много сценариев и часто создаете пакет пустых каталогов

Подход : создайте список каталогов tree, используя этот список в качестве аргументов ввода дляmkdir

tree -dfi --noreport > some_dir_file.txt

-dfi перечисляет только каталоги, печатает полный путь для каждого имени, заставляет дерево не печатать строки отступа,

--noreport Пропускает печать отчета о файле и каталоге в конце списка дерева, просто чтобы выходной файл не содержал лишнего.

Затем перейдите к месту назначения, где вы хотите пустые каталоги, и выполните

xargs mkdir < some_dir_file.txt

0
find source/ -type f  | rsync -a --exclude-from - source/ target/

Копировать каталог только с соответствующим разрешением и владельцем


0

Однострочное решение:

find . -type d -exec mkdir -p /path/to/copy/directory/tree/{} \;

-1

Если вы можете получить доступ с компьютера Windows, вы можете использовать xcopy с / T и / E для копирования только структуры папок (/ E включает пустые папки)

http://ss64.com/nt/xcopy.html

[РЕДАКТИРОВАТЬ!]

Здесь используется rsync для воссоздания структуры каталогов, но без файлов. http://psung.blogspot.com/2008/05/copying-directory-trees-with-rsync.html

Может быть лучше :)


1
К сожалению, наш файловый сервер, обслуживающий CIFS, не работает под управлением Windows, поэтому ничего не может сделать с командами win.
r00fus 08

Спасибо, метод rsync у меня отлично сработал. Он также совместим с пробелами в именах каталогов.
Glutanimate

-1

Вот решение на php, которое:

  • копирует каталоги (не рекурсивно, только один уровень)
  • сохраняет разрешения
  • в отличие от решения rsync, работает быстро даже с каталогами, содержащими тысячи файлов, поскольку он даже не входит в папки
  • не имеет проблем с пробелами
  • должно быть легко читать и настраивать

Создайте файл syncDirs.phpс таким содержанием:

<?php
foreach (new DirectoryIterator($argv[1]) as $f) {
    if($f->isDot() || !$f->isDir()) continue;
        mkdir($argv[2].'/'.$f->getFilename(), $f->getPerms());
        chown($argv[2].'/'.$f->getFilename(), $f->getOwner());
        chgrp($argv[2].'/'.$f->getFilename(), $f->getGroup());
}

Запустите его от имени пользователя с достаточными правами:

sudo php syncDirs.php /var/source /var/destination


Вам не обязательно любить PHP, и вам не обязательно его использовать. Но OP не уточнил, хочет ли он решение на каком-либо конкретном языке, и, нравится ему это или нет, PHP в любом случае установлен во многих системах Linux, поскольку 80% Интернета использует PHP ( w3techs.com/technologies/details/pl- php / все / все ).
Кристофер К.
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.