I've got files in a bunch of subdirectories, and I'd like to flatten them out and move them all to the current directory.

I found this question, but adapting the answer to:

mv * .

didn't work. I just got a lot of warnings looking like:

mv: wil and ./wil are identical

Can anyone help?

I know the files all have unique names, if that helps.

link|improve this question

50% accept rate
feedback

4 Answers

try this:

find ./*/* -type f -print0 | xargs -0 -J % mv % .

More Info: Try the find-stamement alone, it should give you a list with all the files you want to move (leave out the -print0). Example:

probe:test trurl$ find ./*/* -type f
./test_s/test_s_s/testf4
./test_s/test_s_s/testf5
./test_s/testf1
./test_s/testf2
./test_s/testf3
./test_s2/testf6
./test_s2/testf7

with -print0 and xargs you are now creating a list of statements to be executed. The -J % flag means, insert the list element here, so mv $FILE . is executed for every file found.

The above is working for the BSD xargs. If you're using the GNU-version (Linux) take -I % instead of -J %

link|improve this answer
feedback

You can also use the -mindepth option:

find . -type f -mindepth 2 -exec mv -i -- {} . \;

(Together with -maxdepth you could also limit the hierarchy levels from which to collect the files.)

I used mv -i (“interactive”) to make mv ask before overwriting files. With a lot of subdirectories, there may be name clashes you'd like to be warned about.

The -- option stops option processing, so mv doesn't get confused by filenames starting with a hyphen.

Clean up the whole bunch of empty subdirectories with

find . -depth -mindepth 1 -type d -empty -exec rmdir {} \;
link|improve this answer
feedback

Bash 4:

shopt -s globstar
for file in **; do [[ -f "$file" ]] && mv "$file" .; done
link|improve this answer
feedback

You can run the following from your current directory:

mv ./* .

To be safe, you can cp first:

cp ./* .

Verify that your files have been copied to the current directory, then delete from sub directories.

link|improve this answer
This doesn't work. It also doesn't make sense, because every element you'll find with ./* is already in the current directory. – trurl Nov 10 '11 at 13:25
feedback

Your Answer

 
or
required, but never shown

Not the answer you're looking for? Browse other questions tagged or ask your own question.