How can I move all files in subdirectories recursively to a single directory?

I am trying to collect all the files under the current directory and all the subdirectories to one directory. I am trying something like the following

find -type f -exec mv {} collection/{} \; 

the above command won't work because the second {} gives the full path, how can I collect all the files?


Solution 1:

Remove the {} from mv, mv will take it as target directory ignoring any parent directories:

find -type f -exec mv {} collection/ \;

Solution 2:

Instead of using find (which does the job well), you could also use the shell to this end.

Say you want to all files from $PWD to $DEST. The natural attempt would be:

mv $PWD/* $DEST

How does this work? The expression "$PWD/*" expands to the names of all files in that directory. This shell feature is called "globbing". The last argument of mv is the destination directory. If you have very many files, this won't work because the length of the command line is limited.

But the solution has the problem that it omits dot files - or "hidden" files, files and directories whose name start with a ".". To solve this, you have to tell your shell to include dotfiles when globbing. To do this, use

shopt -s dotglob

when using bash (and you probably use bash unless you've changed the default). In this shell, the above command will work for dotfiles as well.

As an aside, in zsh, you have the option to choose this on a case-by-case basis. To do this, put

setopt extendedglob

in your .zshrc. Then you can use

mv $PWD/*(D) $DEST

to move all the files, including dotfiles. (The "D" has the effect of temporarily enabling the "GLOB_DOTS" option).

Now the original question was to move all regular files (not directories) from all subdirectories and their subdirectories to a single directory. This can be accomplished with zsh:

mv $PWD/**/*(D.)

Here the expression **/* makes the globber descend recursively into subdirectories. The D means "also select dotfiles'; the . means "only select regular files, not directories".