#!/bin/bash
cd ~/Desktop/a/
for f in *.jpg; do
target_part="${f%.jpg}"
target="${target_part#Photo }"
mv "$f" -t "${target} "*
done
Explicação
Existem duas substituições de parâmetros que ocorrem aqui. Em primeiro lugar, target_part="${f%.jpg}" remove o .jpg do nome do arquivo, então target="${target_part#Photo }" remove o Photo (+ espaço) na frente. Isso deixa o número na variável target .
Depois, você simplesmente move o arquivo para um diretório que começa com o número em target , ou seja, mv "$f" -t "${target} "* . Isso pressupõe que há apenas um nome de arquivo que começa com cada número e é um diretório.
Mais informações
Houve algumas coisas erradas no seu script. Em primeiro lugar, o shebang estava errado. Em vez de !# , deve ser #! .
Em segundo lugar, não tenho certeza se apenas um erro de digitação, mas a aspa dupla deve estar com " , não “ .
Eu também não sei por que o * em seu parâmetro substitui ${f%Photo*} , nem a que a variável $sub se refere (ele nunca foi atribuído).
Finalmente, em vez de usar ~/Desktop/a/*.jpg para o loop, preferi cd diretamente a ele, para facilitar a substituição de parâmetros.