Given this example directory structure:
rootDir/
├── dir1
│ ├── file1.markdown
│ └── file2.txt
├── dir2
│ └── file3.html
└── dir3
├── file4.mp3
└── file5.c
it is quite easy to flatten rootDir, so that it contains all the files
from the child directories dir1, dir2 and dir3 by moving them via
a single command liner using find:
find rootDir/ -mindepth 2 -type f -exec mv -i '{}' rootDir/ ';'
The -i option for mv will prompt before overwriting a file when a
file name collision occurs. There is an additional tweak for this, e.g.
if every subdirectory contains a README.md file which should be
ignored. The -type option of find can be:
-type f \( ! -iname "README.md" \)
So to flatten the directory structure, but leaving the *.txt files
untouched is accomplished with:
find rootDir/ -mindepth 2 -type f \( ! -iname "*.txt" \) -exec mv -i '{}' rootDir/ ';'
To match all .txt files, but not README.txt:
-type f \( -iname "*.txt" ! -iname "README.txt" \)
The find command line program should be available on most unix-like
operating systems, but they do not all support all options and can
handle regex matching differently (so I read at least).