Solved

Duplicating a directory tree

Posted on 2002-03-08
12
228 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
ID: 6851223
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
ID: 6852922
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
ID: 6854543
could you tell me what is wrong with my script?
0
 
LVL 51

Expert Comment

by:ahoffmann
ID: 6854881
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
ID: 6854956
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
ID: 6854959
did you add the very first line as suggested?
Also replace  ls  by  \ls   or   /bin/ls
0
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 
LVL 5

Accepted Solution

by:
ecw earned 100 total points
ID: 6855067
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
ID: 6855288
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
ID: 6857061
listening.

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

:)
0
 
LVL 3

Expert Comment

by:mliberi
ID: 6865040
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
ID: 6866262
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
ID: 6866268
It is nice to get an answer so small but 100% to the point! Thanks
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

When you do backups in the Solaris Operating System, the file system must be inactive. Otherwise, the output may be inconsistent. A file system is inactive when it's unmounted or it's write-locked by the operating system. Although the fssnap utility…
Let's say you need to move the data of a file system from one partition to another. This generally involves dismounting the file system, backing it up to tapes, and restoring it to a new partition. You may also copy the file system from one place to…
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.:
This video shows how to set up a shell script to accept a positional parameter when called, pass that to a SQL script, accept the output from the statement back and then manipulate it in the Shell.

867 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

18 Experts available now in Live!

Get 1:1 Help Now