Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

Is there a command like

mv --preserve-structure src src/1 src/2/3 dst

which creates dst/1 and dst/2/3? It should work similar to mv src/* dst, but move only the subtrees listed.

share|improve this question
    
you can do this with rsync. –  mattdm Mar 21 '11 at 17:53
    
So, you want each specified dir without descending into subdirectories? –  glenn jackman Mar 21 '11 at 18:52
    
@glenn jackman Actually both, I'm moving a couple of things around like crazy. –  maaartinus Mar 21 '11 at 23:16
add comment

3 Answers

up vote 0 down vote accepted

Under Linux, using rename from the Linux utilities (rename.ul under Debian and Ubuntu):

rename src dst src/1 src/2/3     # dst/2 must exist

With the rename Perl script that Debian and Ubuntu install as prename or rename:

rename 's!^src!dst!' src/1 src/2/3    # dst/2 must exist
rename 'use File::Basename; use File::Path;
        s!^src!dst! && mkpath(dirname($_))' src/1 src/2/3

Here's a shell function that does what you're asking except for the argument order:

mv-preserving-structure () {
  s=${1%/} t=${2%/}; shift 2
  for x; do
    case $x in
      $s/*)
        y=$t${x#$s}
        mkdir -p -- "${y%/*}"
        mv -- "$x" "$t${x#$s}";;
    esac
  done
}
mv-preserving-structure src dst src/1 src/2/3
share|improve this answer
add comment

Assumes bash and GNU find.

mv_preserve_structure() {
  local src_file="$1"
  local dest="$2"
  local rel_dir="$(dirname "$src_file")/"
  rel_dir="${rel_dir#*/}"  # returns "2/3" if rel_dir was "src/2/3"
  mkdir -p "$dest/$rel_dir"
  mv "$src_file" "$dest/$rel_dir"
}

# unlike mv, this requires the destination dir as the first parameter
mv_dirs() {
  local dest="$1"
  shift
  for dir in "$@"; do
    for filename in "$dir"/*; do
      [[ -f "$filename" ]] && mv_preserve_structure "$filename" "$dest"
    done
  done
}

mv_dirs dst src src/1 src/2/3
share|improve this answer
    
I don't get the point of using find. –  Gilles Mar 21 '11 at 20:10
    
@Gilles, just to get a list of files only at the level of the directory. updated. –  glenn jackman Mar 21 '11 at 20:58
add comment
> tar -cf - src/1 src/2/3 | (mkdir dst; cd dst; tar -xv --strip-components=1  -f -)
share|improve this answer
    
Overly complicated for a simple copy, but ok. Except the question was about moving the files. –  Gilles Mar 21 '11 at 20:10
    
Also, that will take every subdirectory under src/1 etc, which I believe the OP does not want. –  glenn jackman Mar 21 '11 at 20:47
    
@glenn jackman, I think he does want to move the whole src/1 subtree although I agree with @Giles that this is copying, not moving, so not really a solution. –  JRW Mar 21 '11 at 21:52
    
Actually, I'm interested in both mv and cp. Both with or without subdirectories. So this solution is useful, too. –  maaartinus Mar 21 '11 at 23:13
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.