A slightly different approach using rename
:
rename 's#.*/(.+)(\.\w+)#mkdir "dest/$1"; "dest/$1/$1$2"#e' source/{a,b}/*
This is essentially just using a regular expression to translate the paths. We use a little bit of Perl (which rename
supports) to create the new directories and rename moves the file at the end.
It isn't too clever. It won't search for cases where there isn't a corresponding file (we could search and remove directories with only one file) and it'll probably explode if there are files without extensions.
$ mkdir -p source/{a,b} dest
$ touch source/a/{ABA,BEB,ACA}.xy
$ touch source/b/{ABA,BEB,ACA}.rr
$ tree
.
├── dest
└── source
├── a
│ ├── ABA.xy
│ ├── ACA.xy
│ └── BEB.xy
└── b
├── ABA.rr
├── ACA.rr
└── BEB.rr
$ rename 's#.*/(.+)(\.\w+)#mkdir "dest/$1"; "dest/$1/$1$2"#e' source/{a,b}/*
$ tree
.
├── dest
│ ├── ABA
│ │ ├── ABA.rr
│ │ └── ABA.xy
│ ├── ACA
│ │ ├── ACA.rr
│ │ └── ACA.xy
│ └── BEB
│ ├── BEB.rr
│ └── BEB.xy
└── source
├── a
└── b
.xy
or.rr