Eu tive que fazer algo assim para separar alguns arquivos algumas vezes. Eu descobri que a expansão variável do bash é sua amiga.
${parameter%word}
${parameter%%word}
Remova o padrão de sufixo correspondente. A palavra é expandida para produzir um padrão exatamente como na expansão do nome do caminho.
Configuração inicial:
-rw-r--r-- 1 falsenames falsenames 0 Jun 5 17:35 5830_1.png
-rw-r--r-- 1 falsenames falsenames 0 Jun 5 17:35 5830_2.png
-rw-r--r-- 1 falsenames falsenames 0 Jun 5 17:35 5830_3.png
-rw-r--r-- 1 falsenames falsenames 0 Jun 5 17:35 5831_1.png
-rw-r--r-- 1 falsenames falsenames 0 Jun 5 17:35 5832_1.png
-rw-r--r-- 1 falsenames falsenames 0 Jun 5 17:35 5832_2.png
$ for i in $(find . -maxdepth 1 -type f); do mkdir -p ${i%_*};mv -v $i ${i%_*}; done
'./5830_3.png' -> './5830/5830_3.png'
'./5831_1.png' -> './5831/5831_1.png'
'./5830_1.png' -> './5830/5830_1.png'
'./5832_1.png' -> './5832/5832_1.png'
'./5832_2.png' -> './5832/5832_2.png'
'./5830_2.png' -> './5830/5830_2.png'
Você pode ser mais específico usando '-name * png' ou alguns outros sinalizadores em encontrar também. Eu corri isso através de um achado com maxdepth definido para verificar apenas o diretório especificado. Desta forma, pode ser executado novamente sem modificação, se mais imagens forem adicionadas a esse diretório. Eu também usei% em vez de %% para que isso não quebre se você precisar especificar um diretório completo que inclua um sublinhado, como "/ home / user / my_files / pngs"
$ for i in $(find move_files -maxdepth 1 -type f); do mkdir -p ${i%_*};mv -v $i ${i%_*}; done
'move_files/5830_3.png' -> 'move_files/5830/5830_3.png'
'move_files/5831_1.png' -> 'move_files/5831/5831_1.png'
'move_files/5830_1.png' -> 'move_files/5830/5830_1.png'
'move_files/5832_1.png' -> 'move_files/5832/5832_1.png'
'move_files/5832_2.png' -> 'move_files/5832/5832_2.png'
'move_files/5830_2.png' -> 'move_files/5830/5830_2.png'