Go Premium for a chance to win a PS4. Enter to Win

x
?
Solved

Duplicating a directory tree

Posted on 2002-03-08
12
Medium Priority
?
237 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
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
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
 
LVL 5

Accepted Solution

by:
ecw earned 400 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

Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

Question has a verified solution.

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

In tuning file systems on the Solaris Operating System, changing some parameters of a file system usually destroys the data on it. For instance, changing the cache segment block size in the volume of a T3 requires that you delete the existing volu…
Introduction Regular patching is part of a system administrator's tasks. However, many patches require that the system be in single-user mode before they can be installed. A cluster patch in particular can take quite a while to apply if the machine…
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 navigate the file tree with the shell. Use pwd to print the current working directory: Use ls to list a directory's contents: Use cd to change to a new directory: Use wildcards instead of typing out long directory names: Use ../ to move…
Suggested Courses
Course of the Month13 days, 10 hours left to enroll

963 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