71

If I run the command mv folder2/*.* folder, I get "argument list too long" error.

I find some example of ls and rm, dealing with this error, using find folder2 -name "*.*". But I have trouble applying them to mv.

DrXCheng
  • 3,992
  • 11
  • 49
  • 72

6 Answers6

138
find folder2 -name '*.*' -exec mv {} folder \;

-exec runs any command, {} inserts the filename found, \; marks the end of the exec command.

Karl Bielefeldt
  • 47,314
  • 10
  • 60
  • 94
31

The other find answers work, but are horribly slow for a large number of files, since they execute one command for each file. A much more efficient approach is either to use + at the end of find, or use xargs:

# Using find ... -exec +
find folder2 -name '*.*' -exec mv --target-directory=folder '{}' +

# Using xargs
find folder2 -name '*.*' | xargs mv --target-directory=folder
Idelic
  • 14,976
  • 5
  • 35
  • 40
  • 1
    Agreed normally, but if a straight `mv` generates an "argument list too long" error, I doubt one just as long built using `find` will work. – Karl Bielefeldt Aug 13 '12 at 22:33
  • 1
    I'm not sure I follow. That's the whole point of the `+` at the end of `find`. If you use that, `find` behaves exactly as the `find | xargs` combination. – Idelic Aug 14 '12 at 14:09
  • The shell errored out when the OP tried to move all the files at once. Both `find` and `xargs` eventually run the same shell command to actually do the move, so they are likely to error out as well. That's why I suggested the one-at-a-time method even though it's slower. – Karl Bielefeldt Aug 14 '12 at 15:11
  • 8
    I suggest you read on how `find ... +` and `xargs` work. They are exactly designed to pass just enough arguments to the command so that the argument list will never be "too long". As a consequence, they may invoke the command several times with different arguments. For each such invocation, the length of the argument list will never exceed the system limit. – Idelic Aug 14 '12 at 18:38
  • I had the problem on 80K+ files to be moved, and the solution of Idelic works correctly. It is fast, and splits the arguments as needed. – Cory86 Oct 17 '13 at 16:44
  • Can anyone share a way to mv files of a particular date or month? Like: |grep 'Nov 14' – Zeeshan Dec 02 '14 at 05:25
  • Oh yes, I just managed to move 300K files in ~10 sec whereas GNU xargs/parallel estimated 2 hours. Thanks! – RReverser Jun 27 '16 at 12:49
  • 2
    Couldn't get either of those commands to work... maybe an old pattern or something, but this works for me on a Mac: `find source_folder -name "*.jpg" -exec mv {} destination_folder \;` – stwhite Sep 25 '17 at 23:56
  • `-bash: /usr/bin/find: Argument list too long` How is this even supposed to work. – imrek Nov 10 '19 at 17:11
  • Suggest: `find ... -print0 | xargs -0 mv --target-directory=folder` - The `-print0` and the `-0` allow you to have spaces in your filenames. As pointed out above, xargs's job is to execute the minimum number of commands needed to get the job done, given the constraints of the arguments' length. You can also force it to batch in a certain quantity like `xargs -n 50`. – artfulrobot Sep 28 '20 at 09:48
  • This worked for me! Thanks. – Bryce Chamberlain Jan 25 '22 at 23:21
4

find folder2 -name '*.*' -exec mv \{\} /dest/directory/ \;

  • Are you literally trying to move a filename named "{}" here? Why the backslashes? Not sure this is a ligit answer..? – Joshua Burns Jan 14 '19 at 18:16
3

First, thanks to Karl's answer. I have only minor correction to this.

My scenario:

Millions of folders inside /source/directory, containing subfolders and files inside. Goal is to copy it keeping the same directory structure.

To do that I use such command:

find /source/directory -mindepth 1 -maxdepth 1 -name '*' -exec mv {} /target/directory \;

Here:

  • -mindepth 1 : makes sure you don't move root folder
  • -maxdepth 1 : makes sure you search only for first level children. So all it's content is going to be moved too, but you don't need to search for it.

Commands suggested in answers above made result directory structure flat - and it was not what I looked for, so decided to share my approach.

Gadget
  • 474
  • 1
  • 5
  • 12
3

This one-liner command should work for you. Yes, it is quite slow, but works even with millions of files.

for i in /folder1/*; do mv "$i" /folder2; done

It will move all the files from folder /folder1 to /folder2.

Sid
  • 4,302
  • 3
  • 26
  • 27
1

find doesn't work with really long lists of files, it will give you the same error "Argument list too long". Using a combination of ls, grep and xargs worked for me:

$ ls|grep RadF|xargs mv -t ../fd/

It did the trick moving about 50,000 files where mv and find alone failed.