find size, cp breaks directory structure

I'm using this now:

find /some/path/with/sourcefiles -type f -size -7M -exec /bin/cp -uv {} /some/path/ \;

but it doesn't preserve the directory structure, also I've tried it with

find /some/path/with/sourcefiles -type f -size -7M -exec /usr/bin/rsync -auv {} /some/path/ \;

but that doesn't either. I've also tried using

find /some/path/with/sourcefiles -type f -size -7M | cpio -pd /some/path/ \;

but I get "too many arguments" error. What am I doing wrong?

Please specify (in words) what you actually want the script to do. It is not obvious from the examples.

cp all the files less than a certain size in a source directory to another directory, but have the same directory and subdirectory in the new location.

There is no simple way. cp will only create a directory tree if it copies a complete tree to begin with. What might work as intended (untested)

find /some/path/with/sourcefiles -type f -size -7M -print | while read file
do
    dir=$( dirname $file )
    echo mkdir -p "/some/other/$dir"
    echo cp -uv "$file" "/some/other/$dir"
done

If it looks like it would work as intended, remove the echo on both lines.

This one was nearly there. There is a spurious "\;" at the end of the line and you need to be passing relative paths not absolute paths.

In your examples the destination and source path overlap because /some/path the same tree as /some/path/with/sourcefiles .
It only makes sense if the destination path is somewhere different.

This idea would preserve the directory structure under /some/path/with/sourcefiles in the destination tree. It also preserves file timestamps but not directory timestamps.
Check "cpio" syntax on your system as I can tell from your "find" command that yours is different from mine.

cd /some/path/with/sourcefiles
find . -type f -size -7M | cpio -pdmv /different/path2

methyl:

find /sourcefiles -type f -size -7M | cpio -pdmv /home/some/path/testdir

worked, but I can't figure out how to copy updates only, didn't find it on <man cpio> or <info cpio> (I would've expected to use -u, but that's something different I think)

pludi:
I modified it slightly like this

find /sourcefiles -type f -size -7M -print | while read file
do
        dir=$(dirname $file)
        echo "mkdir -p /home/some/path/testdir"$dir
        echo "cp -uv "$file "/home/some/path/testdir"$dir
done

but I get the error:

dirname: extra operand `blah/blahblah/somefile.txt'
Try `dirname --help' for more information.

I must be getting close...

The "copy updates only" requirement changes the specification somewhat. The "-u" switch to cpio will allow you to overwrite an existing file. This is not an "updates only" because every file is still copied.

How to copy "updates only"?
Initial feeling is to create a "timestamp" file on entry to the script and refer to the previous version of that "timestamp" file "prev_timestamp" in a "find -newer prev_timestamp" command. Obviously the first time through the script would have to be different from the second and subsequent times.

No idea what Operating System or Shell you have so specific syntax is not possible.

Debian Squeeze & bash, and thanks a lot for your help so far methyl :slight_smile:

[quote=unclecameron;302398861]

find /sourcefiles -type f -size -7M -print | while read file
do
        dir=$(dirname $file)
        echo "mkdir -p /home/some/path/testdir"$dir
        echo "cp -uv "$file "/home/some/path/testdir"$dir
done

but I get the error:

dirname: extra operand `blah/blahblah/somefile.txt'
Try `dirname --help' for more information.


Got spaces in your path, because that message seems like this might be the issue. Change it to find /sourcefiles -type f -size -7M -print | while read file
do
        dir=$(dirname "$file")
        echo "mkdir -p /home/some/path/testdir/$dir"
        echo "cp -uv $file /home/some/path/testdir/$dir"
done

and it should run. Mind tho, as soon as you remove the echo, make sure you have double quotes around the $file and $dir variable in order to remove the special meaning from any whitespace character (so it won't act as an argument separator)

wooohoooo! That worked (just had to delete the trailing slash after testdir), thanks so much for the help :slight_smile: