Gostaria apenas de usar um loop bash para isso:
for i in **/*.txt; do mkdir "${i%.txt}"; done
Se eu executar isso no seu exemplo, obtenho:
$ tree
.
├── 1
│ └── 01-01-2015.txt
├── 2
│ └── 02-02-2016.txt
└── 3
└── 03-03-2017.txt
3 directories, 3 files
$ shopt -s globstar
$ for i in **/*.txt; do mkdir "${i%.txt}"; done
terdon@oregano foo $ tree
.
├── 1
│ ├── 01-01-2015
│ └── 01-01-2015.txt
├── 2
│ ├── 02-02-2016
│ └── 02-02-2016.txt
└── 3
├── 03-03-2017
└── 03-03-2017.txt
6 directories, 3 files
globstar é uma opção bash, explicada em man bash :
globstar
If set, the pattern
**used in a pathname expansion context will match all files and zero or more directories and subdirectories. If the pattern is followed by a/, only directories and subdirectories match.
Assim, após habilitá-lo com shopt -s globstar , o padrão **/*.txt encontrará todos os arquivos (ou dirs) cujo nome termina com .txt .
O ${i%.txt} é a sintaxe da shell para remover uma substring. O formato geral é ${variable%string} e removerá a primeira instância de string do final da variável. Portanto, ${i%.txt}" será o nome do arquivo (incluindo diretórios pai), menos o .txt . Portanto, [passá-lo para mkdir criará o diretório desejado.
Pessoalmente, acho a sintaxe acima muito mais simples, mas veja como fazer isso com find :
find . -name '*.txt' -exec sh -c 'mkdir ${0%.txt}' {} \;
Aqui, o -exec command {} substituirá {} por cada um dos resultados de find e, em seguida, executará command nele. Como o comando aqui é uma chamada para sh -c , o sh assumirá o {} como seu parâmetro posicional zero, $0 . Então, nós executamos a mesma substituição de shell conforme explicado acima para criar o diretório.