-1

I have a question related to my bash shell script. Basically, I need to develop a script that copies certain files from one directory to another. Sounds easy, however, its quite a challenge for me and I hope some of you might help me. So script should work like this:

Scriptname Source_path Destination_path

1) 1st Problem - the source_path might not exist and I need to echo an error message.

2) 2nd Problem - the destination path might not exist, however, I need to create some or all of the directories and then copy the files from source. Else, if directory exists, I just need to copy.

Hope this is clear and hopefully someone might help me thanks!

MrQuartz
  • 21
  • 1
  • 1
  • 4
  • Is this for personal usage? As this sounds like a homework assignment. If its homework, what have you tried so far? – Greg Hilston Apr 08 '15 at 15:28
  • Greg, you are right this is for an assignment. I have the find command to look for certain extensions and skip those which are not needed. – MrQuartz Apr 08 '15 at 17:02

4 Answers4

1

Have a look at this:

 find SOURCEPATH -type f | while read fname
 do 
 mkdir -p TARGETPATH/$(dirname "$fname")
 cp --parents $fname TARGETPATH
 done

Just substitude SOURCEPATH and TARGETPATH and you're good. find will display an errormessage if SOURCEPATH does not exist (1) and mkdir -p will create the directories.

Am_I_Helpful
  • 18,735
  • 7
  • 49
  • 73
steffen
  • 16,138
  • 4
  • 42
  • 81
  • @Allaboutthatbase2 The message does contain `"sourcepath": No such file or directory`. I think, this is clear enough and I don't think, that's worth a downvote :-(. – steffen Apr 08 '15 at 16:03
  • @steffen It's a cool trick. You still complicated it quite a bit. Why not just use the `find ` command itself without all the bash piping and reading? I updated my answer with a variation. The other issue is the `--parents` flag on `cp` is Linux (or perhaps POSIX or GNU) specific – clearlight Apr 08 '15 at 16:12
  • The while loop and pipe is for spaces in fname; the question doesn't sound like empty directories are to be copied (he's talking about files, not the directory tree), that's why i chose this solution. And third: this question is tagged with bash, so --parents parameter will be available. – steffen Apr 08 '15 at 16:19
  • bash has nothing to do with it. bash also runs on Solaris and Mac OS X, and cp on those OSes doesn't have the `--parents` flag. – clearlight Apr 08 '15 at 16:26
1

This script creates the whole directory structure in $2 including empty folders from $1:

#!/bin/sh
[ -z "$2" ] && { echo "Usage: $0 SOURCE DEST"; exit 1; }
[ ! -d "$1" ] && { echo "'$1' does not exist or isn't a directory"; exit 1; }
cp -r "$1" "$2"

If empty directories should be skipped, you need some more logic; unless rsync is available:

#!/bin/sh
[ -z "$2" ] && { echo "Usage: $0 SOURCE DEST"; exit 1; }
[ ! -d "$1" ] && { echo "'$1' does not exist or isn't a directory"; exit 1; }
rsync -mr "$1" "$2"

Explanation:

  • The line with -z verifies that the second argument is not empty
  • The line with ! -d verifies that the directory from first argument exists
  • cp -r copies recursively
  • rsync -mr copies recursively but skips empty directories
  • && and || are widely used substitutions for conditional statements (because they're short)
steffen
  • 16,138
  • 4
  • 42
  • 81
0

Set Variables for arguments one and two, source and dest respectively..

src_dir=$1
dest_dir=$2

Check if directory exists if not exit

[[ -d $src_dir ]] || { echo "source dir not exist"; exit 1 ; }

Create all dirs needed in path

mkdir -p $dest_dir
GL2014
  • 6,016
  • 4
  • 15
  • 22
0

If you want to use the find command, try this:

find SRCPATH -exec mkdir -p DSTPATH/$(dirname "{}") \; -exec cp --parents "{}" DSTPATH \;
  1. Each -exec flag begins a block of shell code to execute and \; terminates it. Getting multiple commands into one -exec has proven problematic for me in the past, so I include two, one for each task.

  2. {} is find's syntax for the variable that indicates the current path find is traversing.

  3. Note: The --parents flag is on the Linux/GNU variation of cp, but is not available on all versions of cp, so the script below is less platform dependent. Further, your question referred specifically to using a script.

  4. Note: SRCPATH and DSTPATH represent the paths of interest. If any directory name of the source or destination contains spaces, you will have to enclose them in " "


Alternatively you can make a bash script.

#!/bin/bash
srcpath=$1
dstpath=$2
if [ ! -d "$srcpath" ]; then
    echo "Source path: $srcpath doesn't exist"
    exit 1
fi
mkdir -p "$dstpath"
cp -r "$srcpath/*" "$dstpath"
  1. The -d flag in the if statement is the flag to test for the yes/no existence of the directory. Here's some information on bash file test operators and other bash comparison operators

  2. The -p flag on mkdir tells it to fill in missing components of the path as necessary. Without the -p, mkdir expects each path component, except the final component of the path, to be present or it will fail.

  3. The -r flag on cp tells cp to recursively copy all the subdirectories, as well as the files indicated by * to the destination, creating those subdirectories as necessary.

  4. Note: The " " around the paths are to protect against errors if any of the path components contain spaces.

clearlight
  • 12,255
  • 11
  • 57
  • 75
  • If you exit with a negative number, the return status will actually show 255 I believe, better to use positive numbers when exiting in bash to get expected return codes later I think. Also, testing for a dir is unnecessary when doing a mkdir -p, I think you can just do the mkdir -p without any problems, I would suspect it does the dir test internally anyhow so you would be doubling the work.. – GL2014 Apr 08 '15 at 15:29