Você não precisa processar coisas como ~ , o shell faz isso por você. É por isso que você pode passar ~/filename para qualquer script ou programa e funciona - todos esses programas não lidam com ~ , seu shell converte o argumento para /home/username/filename e passa para o programa:
$ echo ~/filename
/home/mrozekma/filename
Se você precisar de um nome de arquivo canônico (um que não inclua itens como .. ), use realpath (thanks Neil ):
$ realpath ~/../filename
/home/filename
Quanto a dividir o caminho no nome do diretório e no nome do arquivo, use dirname e basename :
$ dirname /foo/bar/baz
/foo/bar
$ basename /foo/bar/baz
baz