Skip to content
Advertisement

How do I correct this printing out copied files from directory in Unix Bourne Shell?

So i need to write a Unix Bourne Shell to to copy all the files from the directories named dir1 and dir2 into a new directory named dir3.

The script first copies all the files from dir1 into dir3.

The script then copies every file from dir2 to dir3 subject to these conditions: if the file from dir2 is not already present in dir3, or if the dir2 file is newer than the same dir3 file it will overwrite its namesake in dir3.

These should be the output:

These files from dir1 copied into dir3:
a.c b.c file1.c
These new file(s) from dir2 copied into dir3:
file2.c
These file(s) from dir2 copied into dir3 and overwrite(s) their
namesakes in dir3:
a.c
$ ls
cp2.sh dir1 dir2 dir3
$ ls -l dir1
total 12
-rw-r--r-- 1 sxu staff 9 Aug 2 12:52 a.c
-rw-r--r-- 1 sxu staff 9 Aug 2 12:52 b.c
-rw-r--r-- 1 sxu staff 9 Aug 2 12:52 file1.c
$ ls -l dir2
total 12
-rw-r--r-- 1 sxu staff 9 Aug 2 12:53 a.c
-rw-r--r-- 1 sxu staff 9 Aug 2 12:51 b.c
-rw-r--r-- 1 sxu staff 9 Aug 2 12:53 file2.c
$ ls -l dir3
total 16
-rw-r--r-- 1 sxu staff 9 Aug 2 12:53 a.c
-rw-r--r-- 1 sxu staff 9 Aug 2 12:52 b.c
-rw-r--r-- 1 sxu staff 9 Aug 2 12:52 file1.c
-rw-r--r-- 1 sxu staff 9 Aug 2 12:53 file2.c

So technically because dir2 a.c is created 1 minute later than dir1 a.c so it gets pasted in to dir3, overwriting the previously pasted dir1 a.c.

This does not apply to dir2 b.c because it was created earlier than dir1 b.c.

However, my output is something like this:

These files from dir1 copied into dir3:
a.c b.c file1.c
These new file(s) from dir2 copied into dir3:
file2.c
These file(s) from dir2 copied into dir3 and overwrite(s) their
namesakes in dir3:
a.c
b.c

Here is my code:

#!/bin/sh

#Test for directory existence
test -d $1
if [ $? -eq 1 ]
 then
 echo "'$1' directory does not exist."
 exit 0
elif
test -d $2
[ $? -eq 1 ]
 then
 echo  "'$2' directory does not exist."
 exit 0 
elif 
test -d $3
[ $? -eq 0 ]
 then
 echo "'$3' directory does not exist."
 exit 0
fi

#create dir3
mkdir $3

#output for users
echo "These new file(s) from $1 copied into $3:"
ls $1
ls $1 | while read file
do
 cp $1/$file $3/$file
done
echo "These new file(s) from $2 copied into $3:"
ls $2 | while read file
do
 test -f $3/$file
 if [ $? -eq 1 ]
  then
  echo "$file"
 fi
done
echo "These file(s) from $2 copied into $3 and overwrite(s) their namesakes in $3:"
ls $2 | while read file
do
 test -f $3/$file
 if [ $? -eq 0 ]
  then
  cp -u $2/$file $3/$file
  echo "$file"
 else
  cp  $2/$file $3/$file
 fi
done

These bits are wrong i suppose but cannot find out what is wrong…

echo "These file(s) from $2 copied into $3 and overwrite(s) their namesakes in $3:"
ls $2 | while read file
do
 test -f $3/$file
 if [ $? -eq 0 ]
  then
  cp -u $2/$file $3/$file
  echo "$file"
 else
  cp  $2/$file $3/$file
 fi
done

Thanks so much in advance. Much appreciated

Advertisement

Answer

Don’t use a series of elifs, when a loop will do. Only return an exit code of 0 when all is well, not when something goes wrong:

for d in "$1" "$2" ; do
    test -d "$d" || 
    { echo "'$d' directory does not exist."
      exit 1 ; }
done

And mkdir already will return an error if the destination directory exists, so there’s no need to write redundant code. This is enough:

mkdir "$3" || exit

Except for the output to the user, the file copy while loops aren’t really needed. Just use cp with the -u or --update, and -v or --verbose switch; see man cp for details. Both while loops can together be reduced to one line:

cp -uv "$1"/* "$2"/* "$3"
3 People found this is helpful
Advertisement