Search code examples
bashshellsolarissolaris-10

copy files with the base directory


I am searching specific directory and subdirectories for new files, I will like to copy the files. I am using this:

find /home/foo/hint/ -type f -mtime -2 -exec cp '{}' ~/new/ \;

It is copying the files successfully, but some files have same name in different subdirectories of /home/foo/hint/. I will like to copy the files with its base directory to the ~/new/ directory.

test@serv> find /home/foo/hint/ -type f -mtime -2 -exec ls '{}' \;
/home/foo/hint/do/pass/file.txt
/home/foo/hint/fit/file.txt
test@serv> 

~/new/ should look like this after copy:

test@serv> ls -R ~/new/
/home/test/new/pass/:
file.txt

/home/test/new/fit/:
file.txt
test@serv>

platform: Solaris 10.


Solution

  • Since you can't use rsync or fancy GNU options, you need to roll your own using the shell.

    The find command lets you run a full shell in your -exec, so you should be good to go with a one-liner to handle the names.

    If I understand correctly, you only want the parent directory, not the full tree, copied to the target. The following might do:

    #!/usr/bin/env bash
    
    findopts=(
        -type f
        -mtime -2
        -exec bash -c 'd="${0%/*}"; d="${d##*/}"; mkdir -p "$1/$d"; cp -v "$0" "$1/$d/"' {} ./new \;
    )
    
    find /home/foo/hint/ "${findopts[@]}"
    

    Results:

    $ find ./hint -type f -print
    ./hint/foo/slurm/file.txt
    ./hint/foo/file.txt
    ./hint/bar/file.txt
    $ ./doit
    ./hint/foo/slurm/file.txt -> ./new/slurm/file.txt
    ./hint/foo/file.txt -> ./new/foo/file.txt
    ./hint/bar/file.txt -> ./new/bar/file.txt
    

    I've put the options to find into a bash array for easier reading and management. The script for the -exec option is still a little unwieldy, so here's a breakdown of what it does for each file. Bearing in mind that in this format, options are numbered from zero, the {} becomes $0 and the target directory becomes $1...

    d="${0%/*}"            # Store the source directory in a variable, then
    d="${d##*/}"           # strip everything up to the last slash, leaving the parent.
    mkdir -p "$1/$d"       # create the target directory if it doesn't already exist,
    cp "$0" "$1/$d/"      # then copy the file to it.
    

    I used cp -v for verbose output as shown in "Results" above, but IIRC it's also not supported by Solaris, and can be safely ignored.