Differences between revisions 6 and 24 (spanning 18 versions)
Revision 6 as of 2008-11-28 14:16:01
Size: 983
Editor: 89
Comment:
Revision 24 as of 2015-03-05 00:26:24
Size: 2394
Editor: izabera
Comment: syntax hl
Deletions are marked like this. Additions are marked like this.
Line 2: Line 2:
== How can I recreate a directory hierarchy structure, without the files? ==
With the `cpio` program:
Line 3: Line 5:
== How can I recreate a directory structure, without the files? ==
Probably, the most easy to understand one, and the second "find" line does the same with files, creating their "dummy" copies, being empty, but having the original's modification and access times:
{{{#!highlight bash
cd "$srcdir" &&
find . -type d -print | cpio -pdumv "$dstdir"
}}}
or with the `pax` program:
Line 6: Line 11:
 . {{{
 cd "$srcdir"
 find . -type d -exec mkdir -p "$destination"/{} \;
 find . -type f -exec touch -r {} "$destination"/{} \;
{{{#!highlight bash
cd "$srcdir" &&
find . -type d -print | pax -rwdv "$dstdir"
}}}
or with zsh's special globbing:

{{{#!highlight bash
zsh -ec '
cd -- "$srcdir"
dirs=(**/*(/ND))
cd -- "$dstdir"
mkdir -p -- $dirs[@]'
}}}
or with GNU `tar`, and more verbose syntax:

{{{#!highlight bash
cd "$srcdir" &&
find . -type d -print | tar c --files-from - --no-recursion |
  tar x --directory "$dstdir"
}}}
This creates a list of directory names with `find`, non-recursively adds just the directories to an archive, and pipes it to a second `tar` instance to extract it at the target location. As you can see, `tar` is the least suited to this task, but people just adore it, so it has to be included here to appease the `tar` fanboy crowd. (Note: you can't even do this at all with a typical Unix `tar`. Also note: there is no such thing as "standard tar", as both `tar` and `cpio` were intentionally omitted from POSIX in favor of `pax`.)

All but the zsh solution above will fail if directory names contain newline characters. On many modern BSD/GNU systems, at least, they can be trivially modified to cope with that, by using `find -print0` and one of `pax -0` or `cpio -0` or `tar --null` (check your system documentation to see which of these commands you have, and which extensions are available).

If you want to create stub files instead of full-sized files, the following is likely to be the simplest solution. The `find` command recreates the regular files using "dummy" files (empty files with the same timestamps):

{{{#!highlight bash
cd "$srcdir" &&
find . -type f -exec sh -c \
  'dstdir=$1; shift; for i; do touch -r "$i" "$dstdir"/"$i"; done' _ "$dstdir" {} +
Line 12: Line 43:
With the {{{cpio}}} program: If your `find` can't handle `-exec +` then you can use `\;` instead of `+` at the end of the command. See UsingFind for explanations.
Line 14: Line 45:
 . {{{
 cd "$srcdir"
 find . -type d -print | cpio -pdumv "$dstdir"
Or use `find` with `xargs`:

{{{#!highlight bash
find "$src" -type d | sed "s@^$src@@g" | (cd "$dst" && xargs -n1 mkdir)
Line 19: Line 51:
or with GNU {{{tar}}}, and more verbose syntax: (This solution is not recommended, as it fails if `$src` contains any `@` characters, or any characters that have special meaning to `sed`.)
Line 21: Line 53:
 . {{{
 cd "$srcdir"
 find . -type d -print | tar c --files-from - --no-recursion |
   tar x --directory "$dstdir"
}}}

This creates a list of directory names with {{{find}}}, non-recursively adds just the directories to an archive, and pipes it to a second {{{tar}}} instance to extract it at the target location.

 . ''There should be a way to do this with `pax` too....'' - GreyCat
----
CategoryShell

How can I recreate a directory hierarchy structure, without the files?

With the cpio program:

   1 cd "$srcdir" &&
   2 find . -type d -print | cpio -pdumv "$dstdir"

or with the pax program:

   1 cd "$srcdir" &&
   2 find . -type d -print | pax -rwdv  "$dstdir"

or with zsh's special globbing:

   1 zsh -ec '
   2 cd -- "$srcdir"
   3 dirs=(**/*(/ND))
   4 cd -- "$dstdir"
   5 mkdir -p -- $dirs[@]'

or with GNU tar, and more verbose syntax:

   1 cd "$srcdir" &&
   2 find . -type d -print | tar c --files-from - --no-recursion |
   3   tar x --directory "$dstdir"

This creates a list of directory names with find, non-recursively adds just the directories to an archive, and pipes it to a second tar instance to extract it at the target location. As you can see, tar is the least suited to this task, but people just adore it, so it has to be included here to appease the tar fanboy crowd. (Note: you can't even do this at all with a typical Unix tar. Also note: there is no such thing as "standard tar", as both tar and cpio were intentionally omitted from POSIX in favor of pax.)

All but the zsh solution above will fail if directory names contain newline characters. On many modern BSD/GNU systems, at least, they can be trivially modified to cope with that, by using find -print0 and one of pax -0 or cpio -0 or tar --null (check your system documentation to see which of these commands you have, and which extensions are available).

If you want to create stub files instead of full-sized files, the following is likely to be the simplest solution. The find command recreates the regular files using "dummy" files (empty files with the same timestamps):

   1 cd "$srcdir" &&
   2 find . -type f -exec sh -c \
   3   'dstdir=$1; shift; for i; do touch -r "$i" "$dstdir"/"$i"; done' _ "$dstdir" {} +

If your find can't handle -exec + then you can use \; instead of + at the end of the command. See UsingFind for explanations.

Or use find with xargs:

   1 find "$src" -type d | sed "s@^$src@@g" | (cd "$dst" && xargs -n1 mkdir)

(This solution is not recommended, as it fails if $src contains any @ characters, or any characters that have special meaning to sed.)


CategoryShell

BashFAQ/010 (last edited 2023-09-22 06:29:48 by StephaneChazelas)