No shell:
for f in ./IMG_*.jpg ; do
t=${f##*/}
touch "$f" -t "${t:4:8}${t:13:4}.${t:17:2}"
done
Bash, ksh, zsh etc têm a expansão ${var:n:m}
de substring e, se você precisar recursivamente, ative globstar
e use **/IMG_*.jpg
.
Fazer isso com find
também precisa do shell:
$ find -name "IMG_*.jpg" -exec bash -c '
for f; do t=${f##*/}; touch "$f" -t "${t:4:8}${t:13:4}.${t:17:2}" ; done
' sh {} \+
O primeiro argumento para Bash depois do script vai para a variável $0
, que geralmente contém o nome do shell. O restante vai para os parâmetros posicionais $1
, $2
, etc. e for f
ou for f in "$@"
faz um loop sobre eles.
A construção aqui é bastante comum (pelo menos nas respostas unix.SE).
A parte principal do loop aqui é a mesma do primeiro exemplo.
O comando find
em sua pergunta find .. -exec touch -t"$(...)" {} \;
não funciona, pois a substituição do comando está entre aspas duplas, portanto, ele é expandido antes que find
seja executado. O {}
é canalizado literalmente para awk
e acontece que o script awk
imprime apenas um ponto.
Se você colocar a substituição do comando em cotações simples , ela será passada para touch
as-is ( find
só substituiria {}
). touch
obteria o argumento -t$(echo ...)
, cifrões, parênteses e tudo. find
não executa o comando através do shell por si só, precisamos explicitamente fazê-lo, como acima.
No exemplo de aspas simples:
$ find -name x -exec echo 'hello $(foo {})' \;
hello $(foo ./x)