tags:

views:

231

answers:

3

I have a folder with a bunch of log files. Each set of log files is in a folder detailing the time and date that the program was run. Inside these log folders, I've got some video files that I want to extract. All I want is the video files, nothing else. I tried using this command to only copy the video files, but it didn't work because a directory didn't exist.

.rmv is the file extension of the files I want.

$ find . -regex ".*\.rmv" -type f -exec cp '{}' /copy/to/here/'{}'

If I have a folder structure such as:

|- root  
|  
|--- folder1  
|  
|----- file.rmv  
|  
|--- folder2  
|  
|----- file2.rmv  

How can I get it to copy to copy/to/here with it copying the structure of folder1 and folder2 in the destination directory?

A: 

Assuming src is your root and dst is your /copy/to/here

#!/bin/sh

find . -name *.rmv | while read f
do
       path=$(dirname "$f" | sed -re 's/src(\/)?/dst\1/')
       echo "$f -> $path"
       mkdir -p "$path"
       cp "$f" "$path"
done

putting this in cp.sh and running ./cp.sh from the directory over root

Output:

./src/folder1/file.rmv -> ./dst/folder1
./src/My File.rmv -> ./dst
./src/folder2/file2.rmv -> ./dst/folder2

EDIT: improved script version (thanks for the comment)

RC
This won't work if there are spaces in the names. Use `find ... | while read f ...` instead. Also, you should quote filename variables: `"$f"` and `"$path"` for the same reason. Use this: `echo "$f -> $path"` - it's more readable. If your shell supports it (most do), use `$()` instead of [backticks](http://mywiki.wooledge.org/BashFAQ/082). None of those semicolons are necessary, by the way.
Dennis Williamson
+1  A: 

The {} represents the full path of the found file, so your cp command evaluate to this sort of thing:

cp /root/folder1/file.rmv /copy/to/here/root/folder1/file.rmv

If you just drop the second {} it will instead be

cp /root/folder1/file.rmv /copy/to/here

the copy-file-to-directory form of cp, which should do the trick.

Also, instead of -regex, yor could just use the -name operand:

find root -name '*.rmv' -type f -exec cp {} /copy/to/here \;
martin clayton
This doesn't work because it doesn't preserve the folder structure. Inside of the folders, some of the files are named the same. So I don't get all of the files because some keep getting overwritten.
Jonathan Sternberg
+2  A: 

I would just use rsync.

Dennis Williamson
This works if I use rsync and then run rmdir over the directory it gets copied to (since it creates folders that don't have anything in them). I used the command:' rsync -rv root copy/to/here --exclude="*.log" --include="*.rmv" 'The only other files inside the directories were .log files. For some reason, if I only specified include it would still copy all of the files.Thanks.
Jonathan Sternberg
@Jonathan: Take a look at the `--prune-empty-dirs` and `--delete*` options to see if they help.
Dennis Williamson