8

I currently have ~40k RAW images that are in a nested directory structure. (Some folders have as many as 100 subfolders filled with files.) I would like to move them all into one master directory, with no subfolders. How could this be accomplished using mv? I know the -r switch will copy recursively, but this copies folders as well, and I do not wish to have subdirectories in the master folder.

user1067257
  • 443
  • 3
  • 6
  • 15

4 Answers4

16

If your photos are in /path/to/photos/ and its subdirectories, and you want to move then in /path/to/master/, and you want to select them by extension .jpg, .JPG, .png, .PNG, etc.:

find /path/to/photos \( -iname '*.jpg' -o -iname '*.png' \) -type f -exec mv -nv -t '/path/to/master' -- {} +

If you don't want to filter by extension, and just move everything (i.e., all the files):

find /path/to/photos -type f -exec mv -nv -t '/path/to/master' -- {} +

The -n option so as to not overwrite existing files (optional if you don't care) and -v option so that mv shows what it's doing (very optional).

The -t option to mv is to specify the target directory, so that we can stack all the files to be moved at the end of the command (see the + delimiter of -exec). If your mv doesn't support -t:

find /path/to/photos \( -iname '*.jpg' -o -iname '*.png' \) -type f -exec mv -nv -- {} '/path/to/master' \;

but this will be less efficient, as one instance of mv will be created for each file.

Btw, this moves the files, it doesn't copy them.

Remarks.

  • The directory /path/to/master must already exist (it will not be created by this command).
  • Make sure the directory /path/to/master is not in /path/to/photos. It would make the thing awkward!
gniourf_gniourf
  • 44,650
  • 9
  • 93
  • 104
1

Make use of -execdir option of find:

find /path/of/images -type f -execdir mv '{}' /master-dir \;

As per man find:

 -execdir utility [argument ...] ;
     The -execdir primary is identical to the -exec primary with the exception that 
     utility will be executed from the directory that holds the current
     file.  The filename substituted for the string ``{}'' is not qualified.

Since -execdir makes find execute given command from each directory therefore only base filename is moved without any parent path of the file.

anubhava
  • 761,203
  • 64
  • 569
  • 643
  • I'm not sure the `execdir` is mandatory here... and I'm not even sure this does exactly whaty you want (it will also move subdirectories). This is a really messy command `:D`. – gniourf_gniourf Nov 09 '13 at 18:16
  • @gniourf_gniourf: Please test it out. – anubhava Nov 09 '13 at 18:17
  • Check the difference between `find . -execdir echo '{}' \;` and `find . -exec echo '{}' \;` outputs and you will realize how `-execdir` is handy here. – anubhava Nov 09 '13 at 18:19
  • `mkdir -pv anubhava/subdir{1,2}/subsubdir{1,2} master; touch anubhava/subdir{1,2}/subsubdir{1,2}/file; find anubhava -execdir mv {} master \;` Oh dear it doesn't work as expected! – gniourf_gniourf Nov 09 '13 at 18:19
  • Don't worry about me, I know exactly what `-execdir` does `;)`. – gniourf_gniourf Nov 09 '13 at 18:20
  • @gniourf_gniourf: You can very well see the difference between 2 commands I gave in my previous comment. – anubhava Nov 09 '13 at 18:21
  • Have you _tried_ your command? `:)`. Once again, don't worry about me, I know what `-execdir` does. And I'm still claiming that `-execdir` is completely useless here. – gniourf_gniourf Nov 09 '13 at 18:23
  • @gniourf_gniourf: I am not worried about you :) I didn't start commenting. – anubhava Nov 09 '13 at 18:26
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/40875/discussion-between-gniourf-gniourf-and-anubhava) – gniourf_gniourf Nov 09 '13 at 18:27
  • Your command just doesn't work, hence the downvote. I tried to explain to you but you won't listen. – gniourf_gniourf Nov 09 '13 at 18:41
  • @gniourf_gniourf: Don't downvote with so much negativity in mind. Try this command from your created subdir/files and you will know what I am talking about: **`find $PWD/anubhava -type f -execdir mv '{}' $PWD/master/ \;`** – anubhava Nov 09 '13 at 18:47
  • Ah you added `-type f`!!! you see that I was right when I said it didn't work? you have to edit your post so I can remove the downvote. (btw, the `-execdir` is useless, it would work as well with just `-exec`). – gniourf_gniourf Nov 09 '13 at 18:59
  • When you say: _Since `-execdir` makes `find` execute given command from each directory therefore only base filename is moved without any parent path of the file._ This is how `mv` works... – gniourf_gniourf Nov 09 '13 at 19:10
  • A lot of times. Yet, when someone says my answer doesn't work, I do listen to him! Now please edit your answer so I can remove the downvote. – gniourf_gniourf Nov 09 '13 at 19:11
  • I have already edited it by adding `- type f` and tested it again to make sure it works. Again I never said that this is the only way it will work, there are other ways to make it work also. – anubhava Nov 09 '13 at 19:28
0
find <base location of files> -type -f -name \*\.raw -exec mv {} master \;
WhyteWolf
  • 456
  • 2
  • 9
0

If your hierachy is only one level deep, here is another way using the automated tools of StringSolver:

mv -a firstfolder/firstfile.raw firstfile.raw

The -a options immediately applies the similar transformation to all similar files at a nesting level 1 (i.e. for all other subfolders). If you do not trust the system, you can use other options such as -e to explain the transformation or -t to test it on all files.

DISCLAIMER: I am a co-author of this work for academic purposes, and working on a bash script renderer. But the system is already available for testing purposes.

Mikaël Mayer
  • 10,425
  • 6
  • 64
  • 101