Solved

Duplicating a directory tree

Posted on 2002-03-08
12
227 Views
Last Modified: 2010-04-21
I want a bash script that will duplicate the directory structure and the files (only the names of files but not their contents). So for example if called like

test.sh previousdir newdir

it should create the overall directory structure and also the files (empty ones) of previousdir into newdir. So what we tried was to write a recursive functions that will call itslef whenver it comes across a directory, and otherwise touch the file with the same name (see below for the script). The problem is the test
if [ -d $foo ]; always evaluates to false. and we suspect that this is due to some hidden character or something like that when we get $foo from the ls command (in the for loop). Could you please look into this and tell us what we are doing wrong? If I get a working answer within 24 hours I will be happy to add extra 50 points.



#test.sh
echo "source= $1"
echo "destination=$2"
mkdir $2
for foo in $(ls $1)
do
echo $foo
if [ -d $foo ]; then
   echo "directory!"
   echo  $1\/${foo}
   test.sh $1\/${foo} $2\/${foo}
else
   echo "file!"
   echo  $1\/${foo}
   touch $2\/${foo}
fi
done
0
Comment
Question by:oumer
12 Comments
 
LVL 51

Expert Comment

by:ahoffmann
Comment Utility
find $1 -type d -exec mkdir -p ./\{} \;
find $1 -type f -exec touch ./\{} \;
#
# not exactly what you asked for, but simple to understand ;-)
0
 

Expert Comment

by:tsinoa
Comment Utility
Hi!

Below is a perl script that does the job! It's pretty explicit so I hope you'll have no trouble to follow ;)

Try it,

Enjoy, Robert

# START SCRIPT
#! /usr/bin/env perl
# copies complete SourceDir directory structure to DestinationDir but leaves out file content
# calls subroutine branchcp recursively to inspect subbranches

die "Usage: perl dirtreecp.pl SourceDir Destination\n" unless (scalar(@ARGV)==2);
($src,$des)=@ARGV;
die "Source directory \"$src\" does not exist" unless (-d $src);
die "Destination directory \"$des\"does not exist" unless (-d $des);
&branchcp($src,$des);

# recursive subrutine that expands/duplicates all dir branches
sub branchcp {
  my ($src,$des,@list,$item,$src2,$des2); # local variables

  ($src,$des)=@_;
  open LIST, "ls -1 $src |" or die "ls command not successful"; # list src dir content into @list
  @list= <LIST>;
  close LIST;
  foreach $item (@list) { # process all item in a dir list
    chomp($item);
    $src2=$src."\/".$item; # append item to previos src path to create new path
    $des2=$des."\/".$item; # "      "    "  "       des "    "  "      "   "
    if (-d $src2) { # is it directory
      printf "%s -> %s\n", $src2, $des2;
      !system("mkdir $des2") or die "Couldn't create destination directory $des2! $?\n"; # duplicate dir in dest. path
      &branchcp($src2,$des2); # inspect dir's subtree
    } elsif (-f $src2) { # is it file
      printf "%s -> %s\n", $src2, $des2;
      !system("touch $des2") or die "Couldn't create destination file $des! $?\n "; # touch it, create an empty file with the same name in dest. path
    } else { # found something else
      print "$src2 - not a file or directory ... skipped";
    }
  }
}

# END SCRIPT
0
 
LVL 4

Author Comment

by:oumer
Comment Utility
could you tell me what is wrong with my script?
0
 
LVL 51

Expert Comment

by:ahoffmann
Comment Utility
your script does not work if there are directory and/or filenames which contain white spaces.
Also try to add as very first line in your script:

#! /bin/sh
0
 
LVL 4

Author Comment

by:oumer
Comment Utility
There wasn't any directory with white spaces. The problem is the test if [ -d $foo ] always fails, so does the [ -f $foo ] (please refer to my code above). That is why I think when I got the ls and get the name of every file, maybe I am getting also some unprintable character.
0
 
LVL 51

Expert Comment

by:ahoffmann
Comment Utility
did you add the very first line as suggested?
Also replace  ls  by  \ls   or   /bin/ls
0
Highfive + Dolby Voice = No More Audio Complaints!

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

 
LVL 5

Accepted Solution

by:
ecw earned 100 total points
Comment Utility
It doesn't work because "ls dir" list the file in dir and you're not prepending dir to foo.  ie.
  if [ -d "$1/$dir" ] ; then
    ...
  fi
0
 
LVL 38

Expert Comment

by:yuzh
Comment Utility
Hi
  In your script
       "for foo in $(ls $1)"
  You should change it to:

      for foo in `ls -R $1` ; do
          ........
      done

Here 's a sample script for you to do this job:

#!/bin/sh
# first arg = src, 2nd arg=des
cd $1
find . -type d -print |sort >/tmp/dirlist.$$
find . -type f -print | sort >/tmp/filelist.$$
cd $2
for dir in `cat /tmp/dirlist.$$`; do
   mkdir -p $dir
done

for f in `cat /tmp/filelist.$$` ; do
   touch $f
done
echo "Job done !!!!!\n"

0
 
LVL 15

Expert Comment

by:samri
Comment Utility
listening.

(I hope this trick still works with EE revamp).

:)
0
 
LVL 3

Expert Comment

by:mliberi
Comment Utility
test -d $foo

fails because the test is done in the current directory instead of in the source directory.
The same happens, obviously for files.

change it to 'test -d $1/$foo'
0
 
LVL 4

Author Comment

by:oumer
Comment Utility
ecw has said exactly the same thing and it works. Sorry but I am gonna give the points to ecw. Thank you very much, all of you, for such interesting suggestions.
0
 
LVL 4

Author Comment

by:oumer
Comment Utility
It is nice to get an answer so small but 100% to the point! Thanks
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

FreeBSD on EC2 FreeBSD (https://www.freebsd.org) is a robust Unix-like operating system that has been around for many years. FreeBSD is available on Amazon EC2 through Amazon Machine Images (AMIs) provided by FreeBSD developer and security office…
Every server (virtual or physical) needs a console: and the console can be provided through hardware directly connected, software for remote connections, local connections, through a KVM, etc. This document explains the different types of consol…
Learn how to get help with Linux/Unix bash shell commands. Use help to read help documents for built in bash shell commands.: Use man to interface with the online reference manuals for shell commands.: Use man to search man pages for unknown command…
Learn how to find files with the shell using the find and locate commands. Use locate to find a needle in a haystack.: With locate, check if the file still exists.: Use find to get the actual location of the file.:

743 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

13 Experts available now in Live!

Get 1:1 Help Now