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 elif
s, 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"