Это можно сделать очень просто с помощью команды find, как правильно подсказал Алекс: при условии, что каталог для поиска файлов - /path1/to/some/dir, и вы хотите, чтобы файлы были перемещены в /path2/to/other/dir/txt и скоро,
find /path1/some/dir -type f -exec bash -c 'MYDIR=/path2/to/other/dir${0##*.}; [ -d $MYDIR ] && mv $0 $MYDIR || mv $0 /path3/to/miscellanea' {} \;
Эта команда сначала находит все файлы (-type f), содержащиеся в каталоге /path1/to/some/dir и всех его подкаталогах, а затем передает имя каждого такого файла ({}) на небольшой двухслойный bash, который сначала извлекает расширение из имени файла (называемого внутри bash $ 0) и назначает его локальной переменной оболочки MYDIR, затем проверяет наличие подходящего каталога (если такого каталога нет, то, возможно, мы допустили ошибку) , и если каталог существует (&& ...), он перемещает файл в соответствующий каталог, в противном случае (|| ...) он помещает файл в место по умолчанию, /path3/to/miscellanea.
Выше предполагается, что вы уже создали необходимые каталоги, /path2/to/other/dir/txt и так далее. Если вместо этого вы хотите создать их на ходу, вам придется изменить вышеприведенное как:
find /path1/some/dir -type f -exec bash -c 'MYDIR=/path2/to/other/dir/${0##*.}; mkdir -p $MYDIR && mv $0 $MYDIR' {} \;