4

My files have the following structure:

11
--11a
-----a.jpg
-----b.jpg
-----....
--11b
-----d.jpg
-----g.jpg
...

I want to have all the .jpg files in one folder:

11
-a.jpg
-b.jpg
-d.jpg
-g.jpg
...

Basically I have subfolders with many .jpg files and I want to move all of them to one directory (e.g. parent).

I have tried: mv */*.jpg all but I get -bash: /bin/mv: Argument list too long.

Some posts suggest xargs and some other the find solution but unfortunately nothing seems to be working for me.

3
  • Are you certain all the file names are unique? How should conflicts be handled if not? I think find will give you a solution, but you need to answer these questions before I can suggest a solution.
    – AFH
    Commented Oct 6, 2016 at 23:09
  • Yes the file names are unique so there are no conflicts at all. Commented Oct 6, 2016 at 23:45
  • This might work for osx as well. It is an elegant gui solution. Commented Oct 7, 2016 at 16:07

2 Answers 2

6

If the file names are unique, use:

find {base folder}/11 -name "*.jpg" -exec mv {} {base folder}/11/ \;

where {base folder} is where the directory 11 resides.

This runs the mv command on each file in turn: it will be a lot slower than moving all the files in a single mv command, but there will be no restrictions on the length of the argument list.

If some of the file names could be in upper case, you can use -iname instead of -name. You can also add -n to make sure you do not overwrite a file which has been moved already (you need to check that your mv has this option - if not use -i, though this will prompt on conflicts).

You can get rid of any empty directories with:

rmdir {base folder}/11/*

You will need to investigate any directories that remain after this command.

5
  • How about find … -exec mv … +? It should pass multiple paths to mv, taking care of the line length though. Commented Oct 7, 2016 at 16:09
  • @KamilMaciorowski - I'm sceptical: the line length will probably work out the same as in your original mv command, and subject to the same limitations.
    – AFH
    Commented Oct 7, 2016 at 22:34
  • Eh, even worse: it won't work at all. Now i see here that only a <plus-sign> that immediately follows an argument containing only the two characters "{}" shall punctuate the end of the primary expression. Still find {base folder}/11 -name "*.jpg" -exec mv -t {base folder}/11/ {} + should work (it appears this is exactly the purpose of -t option). The downside is the find will match already moved files. One can fight it specifying depth, or accept source and target are the same file error that should do no harm. Commented Oct 8, 2016 at 4:51
  • There is an ordering option on find which allows subdirectories to be traversed in such a way that finding the same file in two places should not occur. Another approach is to process the files a directory at a time, instead of a file at a time: this should limit the mv parameter length. Use something like for d in {base folder}/11/; do [ -d "$d" ] && eval mv "$d/*.jpg" {base folder}/11/; done. This needs to be elaborated, as in this simple form it will generate errors, but it shows the approach. I've just had a gruelling 24 hours, so I can't work out all the niceties at present.
    – AFH
    Commented Oct 8, 2016 at 23:13
  • Works for me, other solutions online did not, thanks!
    – 00-BBB
    Commented Mar 15, 2021 at 16:26
-2

This should be as easy as "mv /.your_extension ./"

2
  • 1
    If down voters put some comment It will be more easy to trace the issue or update the answer. Thanks. Commented Nov 29, 2019 at 12:36
  • this does not answer the question. OP asked to move "all files", not "one file by known extension".
    – frumbert
    Commented Jun 24 at 3:52

You must log in to answer this question.

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