Создайте те же подпапки в другой папке

8

У меня есть каталог fooс подкаталогами. Я хочу создать те же имена подкаталогов в другом каталоге, не копируя их содержимое. Как мне это сделать?

Есть ли способ получить lsвывод в виде расширенного списка скобок?

havakok
источник

Ответы:

11

Попробуй это,

cd /source/dir/path
find . -type d -exec mkdir -p -- /destination/directory/{} \;
  • . -type d Список каталогов по текущему пути рекурсивно.
  • mkdir -p -- /destination/directory/{} создать каталог в месте назначения.

Это полагается на то, findчто поддерживает расширение {}в середине аргументного слова.

Сива
источник
6
Это может сломаться, если любое имя файла или папки на верхнем уровне начинается с тире. Также пропускаются каталоги, начинающиеся с точки. Наконец, имейте в findвиду, что не каждая реализация поддерживает интерполяцию {}в другую строку.
Ройма
1
И это не очень масштабируемо - это займет много времени, если есть миллионы каталогов.
Аркадиуш Драбчик
6
Если есть много вещей , в /source/dir/path, то это , возможно , не с «списком аргументов слишком длинной» ошибка , когда оболочка пытается вызвать findс расширением *. Лучше просто использовать .там. Кроме того, большинство findреализаций позволяет {}использовать его даже при объединении с другой строкой, но это не универсально.
Кусалананда
1
Вы можете использовать .вместо *в этом случае. (Использование xarg для производительности и безопасности, вероятно, потребует внешнего сценария для конкатенации путей)
eckes
24

Использование rsync:

rsync -a --include='*/' --exclude='*' /some/path/dir/ dir

Это воссоздает структуру каталогов, /some/path/dirкак dirв текущем каталоге, без копирования каких-либо файлов.

Любой каталог, найденный в исходном пути, будет создан на цели из-за шаблона включения, но все остальное будет исключено. В качестве побочного эффекта использования -a( --archive) вы получите те же временные метки во всех подкаталогах в цели, что и в источнике. Это также работает для создания локальных структур каталогов из удаленных каталогов (и наоборот).

Кусалананда
источник
Ответ почти всегда rsync!
Arronical
8

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

В этом примере, используя find, будет копировать структуру каталогов от fooдо/tmp/another/

( cd foo && find -type d -exec sh -c 'for d do mkdir -p "/tmp/another/$d"; done' sh {} + )

execЦикл создает множество каталогов под ним foo, который затем передается mkdir. Если у вас нет версии, findкоторая понимает, +вы можете использовать \;за счет эффективности. Подставим mkdirс , echo mkdirчтобы увидеть , что произойдет , не на самом деле делать это.

roaima
источник
1
Или с очевидной петлей,... -exec sh -c 'for dirpath do mkdir -p "/some/path/$dirpath"; done' sh {} +
Кусалананда
точно с GNU find (4.7.0-git) это, похоже, не работает: find: In ‘-exec ... {} +’ the ‘{}’ must appear by itself, but you specified ‘/tmp/another/{}’( -exec ... \;хотя и работает с )
ilkkachu
Кусалананда, улучшение принято, спасибо
roaima
Ilkkachu Я уверен, что я тестировал, /path/to/{}но я не могу найти ни одной версии, где она работает, поэтому я адаптировал решение. Спасибо
Ройма
3

С оболочкой bash вы можете запросить расширение каждого каталога с помощью globstarопции:

shopt -s globstar

а затем скопируйте каталоги с помощью цикла:

for dir in **/
do
  mkdir -p /path/to/dest/"$dir"
done

... или если бы вы думали, что они все подойдут в течение одного звонка mkdir:

set -- **/
mkdir -- "${@/#//path/to/dest/}"

Это синтаксис массива bash, который гласит: «возьмите каждый элемент $@массива и замените начало каждого из них на /path/to/dest/.

Я не знаю, lsкак напрямую получить вывод в виде списка расширений. Если вы попытаетесь втиснуть вывод **/расширения в расширение фигурной скобки, вам нужно быть осторожным:

  • экранировать запятые в выводе
  • избежать любой {или ${последовательности
  • убедитесь, что результирующая строка не превышает доступное пространство аргументов командной строки

Я бы не рекомендовал это.

Джефф Шаллер
источник
2

Этот вопрос является дубликатом кросс-сайта /superuser/1389580/copy-directory-structure-only-at-year-end

Этот вид задачи является классическим вариантом использования для mtree:

$ mkdir new-tree
$ mtree -cp old-tree | mtree -tdUp new-tree
.:      modification time (Tue Sep 24 14:27:07 2019, Tue Sep 24 16:34:57 2019, modified)
./bar missing (created)
./bar/bar2 missing (created)
./bar/bar2/bar3 missing (created)
./bar/bar2/bar3/bar4 missing (created)
./foo missing (created)
./foo/foo2 missing (created)
./foo/foo2/foo3 missing (created)

Вышеприведенное создает все каталоги, под new-treeкоторыми присутствовали old-tree. mtreeоднако не устанавливает метки времени для вновь создаваемых каталогов, поэтому результирующее дерево выглядит так:

$ find old-tree new-tree -ls
 20147  1 drwx--x---   4 jim   jim   5 Sep 24 14:27 old-tree
 20048  1 drwx--x---   3 jim   jim   4 Sep 24 14:27 old-tree/foo
 20363  1 -rw-------   1 jim   jim   0 Sep 24 14:27 old-tree/foo/file
 20073  1 drwx--x---   3 jim   jim   4 Sep 24 14:27 old-tree/foo/foo2
 20074  1 drwx--x---   2 jim   jim   3 Sep 24 14:27 old-tree/foo/foo2/foo3
 20365  1 -rw-------   1 jim   jim   0 Sep 24 14:27 old-tree/foo/foo2/foo3/file
 20364  1 -rw-------   1 jim   jim   0 Sep 24 14:27 old-tree/foo/foo2/file
 20051  1 drwx--x---   3 jim   jim   4 Sep 24 14:27 old-tree/bar
 20077  1 drwx--x---   3 jim   jim   4 Sep 24 14:27 old-tree/bar/bar2
 20368  1 -rw-------   1 jim   jim   0 Sep 24 14:27 old-tree/bar/bar2/file
 20078  1 drwx--x---   3 jim   jim   4 Sep 24 14:27 old-tree/bar/bar2/bar3
 20369  1 -rw-------   1 jim   jim   0 Sep 24 14:27 old-tree/bar/bar2/bar3/file
 20079  1 drwx--x---   2 jim   jim   3 Sep 24 14:27 old-tree/bar/bar2/bar3/bar4
 20370  1 -rw-------   1 jim   jim   0 Sep 24 14:27 old-tree/bar/bar2/bar3/bar4/file
 20366  1 -rw-------   1 jim   jim   0 Sep 24 14:27 old-tree/bar/file
 20362  1 -rw-------   1 jim   jim   0 Sep 24 14:27 old-tree/file
134489  1 drwx--x---   4 jim   jim   4 Sep 24 16:34 new-tree
134490  1 drwx--x---   3 jim   jim   3 Sep 24 16:34 new-tree/bar
134491  1 drwx--x---   3 jim   jim   3 Sep 24 16:34 new-tree/bar/bar2
134492  1 drwx--x---   3 jim   jim   3 Sep 24 16:34 new-tree/bar/bar2/bar3
134493  1 drwx--x---   2 jim   jim   2 Sep 24 16:34 new-tree/bar/bar2/bar3/bar4
134494  1 drwx--x---   3 jim   jim   3 Sep 24 16:34 new-tree/foo
134495  1 drwx--x---   3 jim   jim   3 Sep 24 16:34 new-tree/foo/foo2
134496  1 drwx--x---   2 jim   jim   2 Sep 24 16:34 new-tree/foo/foo2/foo3

Если вы предпочитаете, чтобы new-treeвременные метки совпадали с указанными old-tree, просто запустите mtreeснова. Поскольку каталоги уже существуют, mtreeизменит временные метки в соответствии со спецификацией источника:

$ mtree -cp old-tree | mtree -tdUp new-tree
.:      modification time (Tue Sep 24 14:27:07 2019, Tue Sep 24 16:34:57 2019, modified)
bar:    modification time (Tue Sep 24 14:27:07 2019, Tue Sep 24 16:34:57 2019, modified)
bar/bar2: 
        modification time (Tue Sep 24 14:27:07 2019, Tue Sep 24 16:34:57 2019, modified)
bar/bar2/bar3: 
        modification time (Tue Sep 24 14:27:07 2019, Tue Sep 24 16:34:57 2019, modified)
bar/bar2/bar3/bar4: 
        modification time (Tue Sep 24 14:27:07 2019, Tue Sep 24 16:34:57 2019, modified)
foo:    modification time (Tue Sep 24 14:27:07 2019, Tue Sep 24 16:34:57 2019, modified)
foo/foo2: 
        modification time (Tue Sep 24 14:27:07 2019, Tue Sep 24 16:34:57 2019, modified)
foo/foo2/foo3: 
        modification time (Tue Sep 24 14:27:07 2019, Tue Sep 24 16:34:57 2019, modified)
$ find old-tree new-tree -ls
 20147  1 drwx--x---   4 jim   jim   5 Sep 24 14:27 old-tree
 20048  1 drwx--x---   3 jim   jim   4 Sep 24 14:27 old-tree/foo
 20363  1 -rw-------   1 jim   jim   0 Sep 24 14:27 old-tree/foo/file
 20073  1 drwx--x---   3 jim   jim   4 Sep 24 14:27 old-tree/foo/foo2
 20074  1 drwx--x---   2 jim   jim   3 Sep 24 14:27 old-tree/foo/foo2/foo3
 20365  1 -rw-------   1 jim   jim   0 Sep 24 14:27 old-tree/foo/foo2/foo3/file
 20364  1 -rw-------   1 jim   jim   0 Sep 24 14:27 old-tree/foo/foo2/file
 20051  1 drwx--x---   3 jim   jim   4 Sep 24 14:27 old-tree/bar
 20077  1 drwx--x---   3 jim   jim   4 Sep 24 14:27 old-tree/bar/bar2
 20368  1 -rw-------   1 jim   jim   0 Sep 24 14:27 old-tree/bar/bar2/file
 20078  1 drwx--x---   3 jim   jim   4 Sep 24 14:27 old-tree/bar/bar2/bar3
 20369  1 -rw-------   1 jim   jim   0 Sep 24 14:27 old-tree/bar/bar2/bar3/file
 20079  1 drwx--x---   2 jim   jim   3 Sep 24 14:27 old-tree/bar/bar2/bar3/bar4
 20370  1 -rw-------   1 jim   jim   0 Sep 24 14:27 old-tree/bar/bar2/bar3/bar4/file
 20366  1 -rw-------   1 jim   jim   0 Sep 24 14:27 old-tree/bar/file
 20362  1 -rw-------   1 jim   jim   0 Sep 24 14:27 old-tree/file
134489  1 drwx--x---   4 jim   jim   4 Sep 24 14:27 new-tree
134490  1 drwx--x---   3 jim   jim   3 Sep 24 14:27 new-tree/bar
134491  1 drwx--x---   3 jim   jim   3 Sep 24 14:27 new-tree/bar/bar2
134492  1 drwx--x---   3 jim   jim   3 Sep 24 14:27 new-tree/bar/bar2/bar3
134493  1 drwx--x---   2 jim   jim   2 Sep 24 14:27 new-tree/bar/bar2/bar3/bar4
134494  1 drwx--x---   3 jim   jim   3 Sep 24 14:27 new-tree/foo
134495  1 drwx--x---   3 jim   jim   3 Sep 24 14:27 new-tree/foo/foo2
134496  1 drwx--x---   2 jim   jim   2 Sep 24 14:27 new-tree/foo/foo2/foo3
Джим Л.
источник