I want to write a bash script that accepts, as an input argument, a file specification that includes one or more uses of the special characters ., .., and ~. I want my script's output to echo Bash's full path interpretation of my script.

Here is script I have tried:

a=$(ls -l -o -g "${1}" | cut --delimiter=' ' --fields=1-6 --complement -)

echo "\\"${a}\\""

If I issue command: myscript ~/.local/../.profile

The result returned is: /home/OldManK/.local/../.profile. But, I want: /home/OldManK/.profile.

Another example: myscript ~/./.profile returns: /home/OldManK/./.profile, but, I want: /home/OldManK/.profile.

Another (executed from /home/OldManK/.local): myscript ../.profile returns: ../.profile, but, I want: /home/OldManK/.profile.

Any alternate approaches, please?

  • Please "edit" your post and use code formatting for your code: that will greatly increase readability of your post and increase the chance someone reads it entirely through.
    – vanadium
    Oct 1 at 8:34
  • As a general rule, parsing ls is a very bad idea that should be avoided unless you have 100% control over the input file names, but even then it will break when using -l since the dates can change. See mywiki.wooledge.org/ParsingLs
    – terdon
    Oct 1 at 12:07
  • 3
    Note that it isn't actually bash responsible for parsing things like ../ -- this is done by the operating system kernel as part of handling open() and similar calls. Oct 1 at 16:24
  • 1
    Expansion of the ~ is done by the calling shell before it's passed to your script as an argument. That is, when you run myscript ~/.local/../.profile, the script actually receives "/home/OldManK/.local/../.profile" as its argument. If you want your script to handle ~ itself, things get more complicated (see this stackoverflow question). Oct 1 at 22:28
  • What you're looking for is sometimes called the "canonical" form of a path, with foo/../bar resolved (to bar if foo wasn't a symlink.) What's a "canonical path"? . The other part is shell-expansion of shell meta-characters like ~. Oct 2 at 7:13

1 Answer 1


Use realpath:

$ realpath ~/.local/bin/../mycommand

From man realpath:

    Print the resolved absolute file name; all but the last component must exist
  • Thanks, Jos. Perfect.
    – OldManK
    Oct 1 at 8:34
  • 2
    If my post was helpful, please check the mark next to it to mark the question as answered. Thanks.
    – Jos
    Oct 1 at 9:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.