Crea le stesse sottocartelle in un'altra cartella


8

Ho una directory foocon sottodirectory. Vorrei creare gli stessi nomi delle sottodirectory in un'altra directory senza copiarne il contenuto. Come faccio a fare questo?

C'è un modo per ottenere l' lsoutput come un elenco di espansione del controvento?

Risposte:


11

Prova questo,

cd /source/dir/path
find . -type d -exec mkdir -p -- /destination/directory/{} \;
  • . -type d Elencare ricorsivamente le directory nel percorso corrente.
  • mkdir -p -- /destination/directory/{} crea directory a destinazione.

Questo si basa su un findsupporto che si espande {}nel mezzo di una parola argomento.


6
Ciò potrebbe interrompersi se qualsiasi nome di file o cartella nel livello superiore inizia con un trattino. Omette anche le directory che iniziano con un punto. Infine, tieni presente che non tutte le implementazioni findsupportano l'interpolazione di {}in un'altra stringa.
roaima,

1
E non è molto scalabile - ci vorrà molto tempo se ci sono milioni di directory.
Arkadiusz Drabczyk,

6
Se ci sono molte cose dentro /source/dir/path, allora questo potrebbe fallire con un errore "lista argomenti troppo lunga" quando la shell tenta di chiamare findcon l'espansione di *. Meglio usare solo .lì. Inoltre, la maggior parte delle findimplementazioni consente {}di essere utilizzata anche se concatenata con un'altra stringa, ma non è universale.
Kusalananda

1
Puoi usare .Invece di *in questo caso. (L'uso di xarg per prestazioni e sicurezza richiederebbe probabilmente uno script esterno per la concatenazione del percorso)
eckes

24

Utilizzando rsync:

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

Ciò ricrea la struttura della directory /some/path/dircome dirnella directory corrente, senza copiare alcun file.

Qualsiasi directory trovata nel percorso di origine verrebbe creata sulla destinazione a causa del modello di inclusione, ma qualsiasi altra cosa sarebbe esclusa. Come effetto collaterale dell'uso di -a( --archive), otterrai gli stessi timestamp su tutte le sottodirectory nel target come nella sorgente. Questo funziona anche per la creazione di strutture di directory locali da directory remote (e viceversa).


La risposta è quasi sempre rsync!
Arronical

8

È possibile utilizzare findper attraversare la struttura di origine e chiamare mkdirper ogni directory che incontra.

Questo esempio, usando find, copia la struttura della directory da fooa/tmp/another/

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

Il execciclo crea il set di directory sottostanti foo, che viene quindi passato al file mkdir. Se non si dispone di una versione findche capisce, +è possibile utilizzare \;a costo dell'efficienza. Sostituisci mkdircon echo mkdirper vedere cosa sarebbe successo senza farlo davvero.


1
O con l'ovvio ciclo,... -exec sh -c 'for dirpath do mkdir -p "/some/path/$dirpath"; done' sh {} +
Kusalananda

esattamente con GNU find (4.7.0-git) questo non sembra funzionare: find: In ‘-exec ... {} +’ the ‘{}’ must appear by itself, but you specified ‘/tmp/another/{}’(funziona con -exec ... \;, comunque)
ilkkachu

Kusalananda, improvvisazione presa, grazie
roaima,

Ilkkachu sono sicuro di averlo provato /path/to/{}ma ora non riesco a trovare alcuna versione in cui funzioni, quindi ho adattato la soluzione. Grazie
roaima,

3

Con la shell bash, potresti chiedere l'espansione di ogni directory con l' globstaropzione:

shopt -s globstar

e quindi copia le directory con un ciclo:

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

... o se pensavi che sarebbero rientrati tutti in una chiamata a mkdir:

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

Questa è la sintassi dell'array bash che dice: "prendi ogni elemento $@dell'array e sostituisci l'inizio di ciascuno di essi con /path/to/dest/.

Non sono a conoscenza di un modo per ottenere lsl'output direttamente come elenco di espansione del controvento. Se hai provato a massaggiare l'uscita **/dell'espansione in un'espansione di controvento, dovrai fare attenzione a:

  • sfuggire alle virgole nell'output
  • sfuggire a qualsiasi {o ${sequenza
  • assicurarsi che la stringa risultante non superi lo spazio degli argomenti della riga di comando disponibile

Non lo consiglierei.


2

La domanda è un duplicato su più siti di /superuser/1389580/copy-directory-structure-only-at-year-end

Questo tipo di attività è un classico caso d'uso per 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)

Quanto sopra crea tutte le directory sotto new-treeche erano presenti sotto old-tree. mtreenon imposta i timestamp nelle directory appena create, quindi l'albero risultante è simile al seguente:

$ 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

Se si preferisce che i new-treetimestamp corrispondano a quelli in old-tree, eseguire semplicemente di mtreenuovo. Poiché le directory esistono già, mtreemodificheranno i timestamp in modo che corrispondano alle specifiche di origine:

$ 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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.