Big Millz
Big Millz

Reputation: 93

Getting all files from various folders and copying them with unique names

Currently using this command to get all my "fanart" from my TV folder, and dump it into a single folder.

find /volume1/tv/ -type f \( -name '*fanart.jpg'* -o -path '*/fanart/*.jpg' -o -path '*/extrafanart/*.jpg' \) -exec cp {} /volume1/tv/_FANART \;

Here's the issue: a lot of these files have the same name, and can't be dumped into the same folder. Example:

Is there a way to copy these files from their respective folders and give them a unique name in the destination folder? Name needn't be anything descriptive, random is just fine.

Upvotes: 4

Views: 2006

Answers (3)

gniourf_gniourf
gniourf_gniourf

Reputation: 46813

If you want to use the md5sum as the new name:

find /volume1/tv/ -type d -path '/volume1/tv/_FANART' -prune -o -type f \( -name '*fanart.jpg'* -o -path '*/fanart/*.jpg' -o -path '*/extrafanart/*.jpg' \) -exec sh -c 'md5=$(md5sum < "$0") && md5=${md5%% *}.jpg && echo cp "$0" "/volume1/tv/_FANART/$md5"' {} \;

Every thing happens in the sh command (all commands are separated by && but I omitted the && for clarity):

md5=$(md5sum < "$0")
md5=${md5%% *}.jpg
cp "$0" "/volume1/tv/_FANART/$md5"'

the $0 expands to the filename processed. We first compute the md5sum of the file, then only keep the md5sum (md5sum puts a hyphen next to the hash) and append .jpg to that, and finally we copy the file into the target folder, with the computed name.

Notes.

  • I added

    -type d -path '/volume1/tv/_FANART` -prune -o
    

    to your command to omit this folder, since you very likely don't want to process it; it would actually be weird to process it, as its content is changed throughout find's traversal.

  • I left an echo in the command, so that absolutely nothing is copied (as is, it's 100% safe, you can just copy and paste it in your terminal): it only shows what commands are going to be performed (and you'll also see how fast/slow it is).
  • The command is 100% safe regarding funny filenames with spaces, newlines, globs, etc.
  • I used md5sum < fileand not md5sum file, because if the filename file contains special characters (like backslashes, newlines, etc.), md5sum (at least my version) prepends the hash with a backslash. Weird. By not giving a filename, we're safe, this won't happen.

Upvotes: 2

repzero
repzero

Reputation: 8412

find /volume1/tv/ -type f \( -name '*fanart.jpg'* -o -path '*/fanart/*.jpg' -o -path '*/extrafanart/*.jpg' \) -exec cp --backup=numbered  {} /volume1/tv/_FANART \;

..

cp --backup=numbered  {}

If the file exists, this will not overwrite but make a backup with a number assigned.

The files will be hidden. Ctrl+H to view hidden files

Upvotes: 2

Thomas Dickey
Thomas Dickey

Reputation: 54475

You could copy the files while giving them names according to their locations in the original directory tree. For instance (":" is legal but unusual in filenames), your "find" command could call a shell script (rather than "cp" directly), which might look like this:

#!/bin/sh
case "x$1" in
x/volume1/tv/_FANART/*)
    ;;
*)
    target=`echo "$1" | sed -e 's,^/volume1/tv/,,' -e s,/,:,g`
    cp "$1" "$2/$target"
    ;;
esac

and the corresponding "-exec" would be

-exec myscript "{}" /volume1/tv/_FANART \;

By the way, the source/destination on the original example are in the same directory tree "/volume1/tv", which is why the sample script uses a case statement - to exclude files already copied to the _FANART folder.

Upvotes: 1

Related Questions