0

I'm trying to batch move/organize a large number of files (.jpg) from nested subdirectories to a relative directory. The structure is pre-planned. Just not 100% sure what the most efficient and safest way to do it is.

Sample structure:

/directory/subdir/jpg/
/directory/subdir/source/something.jpg
/directory/subdir/source/something.tif
/directory/subdir/source/something-else.jpg
/directory/subdir/source/something-else.tif
/directory/subdir/source/another-file.jpg
/directory/subdir/source/another-file.tif
/directory/another-subdir/jpg/
/directory/another-subdir/source/yet-another-file.jpg
/directory/another-subdir/source/yet-another-file.tif

Goal is to get it to this...

/directory/subdir/jpg/something.jpg
/directory/subdir/jpg/something-else.jpg
/directory/subdir/jpg/another-file.jpg
/directory/subdir/source/something.tif
/directory/subdir/source/something-else.tif
/directory/subdir/source/another-file.tif
/directory/another-subdir/jpg/yet-another-file.jpg
/directory/another-subdir/source/yet-another-file.tif

I thought about something like this. Just not sure if it's going to toast my structure. We're talking about tens of gigs of data, and thousands of files that are critical to our client's organization.

find /directory -name \*.jpg -exec mv {} ../jpg/ \;

If there's some form of "dry run" anyone might know about that I can use to visually test before actually executing, that'd be amazing. Thank you!

UPDATE:

Actually, I'm now trying to do the same thing locally on my Mac, and getting this error. Any clever workarounds?

$ find -name "*.jpg" -execdir pwd \; -execdir echo mv -v '{}' ../jpg \;
find: illegal option -- n
usage: find [-H | -L | -P] [-EXdsx] [-f path] path ... [expression]
       find [-H | -L | -P] [-EXdsx] -f path [path ...] [expression]

1 Answer 1

2

You can do a dry run by simply including echo:

find /directory -name \*.jpg -exec echo mv {} ../jpg/ \;

But that will not do what you want as ../jpg is always evaluated in the current directory, hence would move all jpg images to $PWD/../jpg.

This should work as expected:

find /directory -name "*.jpg" -execdir pwd \; -execdir echo mv -v '{}' ../jpg \;

because -execdir is

like -exec, but the specified command is run from the subdirectory containing the matched file, which is not normally the directory in which you started find. This a much more secure method for invoking commands, as it avoids race conditions during resolution of the paths to the matched files.

But of course as "We're talking about tens of gigs of data, and thousands of files that are critical to our client's organization.", always have an up-to-date backup at hand...

3
  • I didn't even know about -execdir! Awesome solution!! Jul 16, 2014 at 17:51
  • @WillAshworth: Glad my answer helped -- please consider to accept it. Regarding your update: The error probably is because I ommited the starting directory, which is equal to ., but IMHO only with GNU find. I updated my second command.
    – mpy
    Jul 16, 2014 at 20:39
  • You're a master. Thank you for your help today. That solved it without issue! Jul 16, 2014 at 20:45

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .