36

How can I move the files contained in all subdirectories to the current directory, and then remove the empty subdirectories?

I found this question, but adapting the answer to:

mv * .

did not work; I received a lot of warnings looking like:

mv: wil and ./wil are identical

The files contained in the subdirectories have unique names.

6 Answers 6

49

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 {} \;
3
  • Is there also a way to skip the question for overwriting the files by not overwrting them?
    – Filnor
    Commented Aug 13, 2018 at 8:27
  • 3
    Options for mv: -n, --no-clobber: do not overwrite an existing file. You might be interested in -b, --backup, too. Commented Aug 17, 2018 at 9:24
  • Use find . -type f -mindepth 2 -exec mv -- {} . \; if you don't care about files which are overwritten. Commented Nov 30, 2022 at 7:01
8
mv */* .

It will move all files from all subdirectories to current directory.

If you need some cleanup, you could use

find . -type d -empty -delete

It will delete all empty subdirectories.

1
  • This will only go one directory deep on Mac OS. Commented Jun 7, 2023 at 3:49
5

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 %

0

Bash 4:

shopt -s globstar
for file in **; do [[ -f "$file" ]] && mv "$file" .; done
-2

1 quick trick, only works if your files have extensions (with a dot):

mv *.* subdir/
mv .* subdir/
-2

Just run this command:-)

mv **/*.* .

1

You must log in to answer this question.

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