9

Pretty self explanatory.

The first argument should be:

  • Checked if the file exists
  • Echo that file's absolute path

For example:

+akiva@akiva-ThinkPad-X230:~$ ./myscript myfile.txt
/home/akiva/myfile.txt

Thanks

marked as duplicate by muru bash Mar 15 '17 at 0:52

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • Akiva , filenames in spaces are something that shell has to take care of and pass to other commands. Individual commands do not deal with spaces. Please read on word-splitting done by shells. If you want commands to take care of spaces and special characters, use double or single quotes around a path – Sergiy Kolodyazhnyy Mar 14 '17 at 17:44
  • 1
    Please don't add requirements like that. Either quote the output of the script, or pass it through sed 's# #\ #g' – terdon Mar 14 '17 at 17:44
  • @Serg The issue with say, single quotes, is that file names often have single quotes within them, so I will still need a method or good sed command to deal with that. Sorry about adding the requirement though; I did not anticipate that I would run into that issue. – Akiva Mar 14 '17 at 17:46
  • 1
    @Akiva All you really need is to type out your filename as usual, and enclose it into double quotes. Just mix and match. If it has spaces only, single or double quotes are fine. Seriously, this is something that belongs in its own question, and quoting has been widely discussed already. I would say it is beyond the scope of this post – Sergiy Kolodyazhnyy Mar 14 '17 at 18:03
  • 1
    Try my update and let me know if it flies – George Udosen Mar 14 '17 at 18:17
7

If your script is

#!/bin/bash
[[ -e "$1" ]] && readlink -f -- "$1"

And has execute permission (chmod u+x scriptname) You can enter

./scriptname file

To get the full path if the file exists (although Serg is right that the test is redundant if we use readlink -e and George is right to use realpath rather than readlink)

Notes

  • [[ -e "$1" ]] test whether $1, the first argument to the script, exists
  • && if it does (if the previous command was successful) then do the next command
  • readlink -f -- "$1" print the full path (to the real file, even if $1 is a symlink)

OP requested special characters be printed with escapes. There must be a smart way* but I did it like this (although it won't deal with single quotes - but those cannot be escaped anyway)

[[ -e "$1" ]] && readlink -f -- "$1" | sed -r 's/\||\[|\]| |!|"|\$|%|\^|&|\*|\(|\)\{|\}|\#|@|\;|\?|<|>/\\&/g'

If it's only spaces you're worried about, you could make that

sed 's/ /\\ /g'

This would get single quotes (not very usefully) and spaces

sed -r "s/'| /\\\&/g"

But I don't think you can catch both single quotes and double quotes...

* Here's the smart way, 100% credit to steeldriver

[[ -e "$1" ]] && printf "%q\n" "$(readlink -f -- "$1")"
  • 1
    wow... was not expecting that. Was going to start a new question. That is a really nice sed command. – Akiva Mar 14 '17 at 18:07
  • 2
    Perhaps somehow using printf '%q' is the "smart way"? e.g. printf "%q\n" "$(readlink -f -- "$1")" – steeldriver Mar 14 '17 at 18:11
  • @steeldriver oh that is it! hmm I am editing it in. Thank you very much! – Zanna Mar 14 '17 at 18:25
8

Script is not necessary. A single readlink command is sufficient:

$ cd /etc/

$ readlink -e passwd
/etc/passwd

From the man readlink:

   -e, --canonicalize-existing
          canonicalize by following every symlink in every component
          of the given name recursively, all components must exist
  • Well I need the script to pass arguments to my build folder :P – Akiva Mar 14 '17 at 17:20
  • 1
    @Akiva so insert the command into the script :p Script is nothing but collection of commands. – Sergiy Kolodyazhnyy Mar 14 '17 at 17:22
7
#!/bin/bash

[[ -e "$1" ]] && echo realpath -e "$1"

Update to take care of non-alphanumeric characters:

#!/bin/bash

[[ -e "$1" ]] && echo "$1" | sed -r 's/[^a-zA-Z0-9\-]/\//g' | realpath -e "$1"

Prepare script: chmod +x script_name, then

use it : ./script_name filename

Information:

  1. [[ -e "$1" ]]: check if the passed file exists.
  • 1
    This is a good command, but should also be noted that some shells have built-in readlink command. My shell, mksh for instance, has that as built-in, so syntax is different. Please note that in your answer. – Sergiy Kolodyazhnyy Mar 14 '17 at 17:27
  • 1
    @Serg he's using realpath, not readlink. – terdon Mar 14 '17 at 17:33
  • 1
    @Serg, not an expert but are you saying that your shell would not give the right output with this command? – George Udosen Mar 14 '17 at 17:34
  • 1
    Ah, no. @Serg meant that realpath which is what you're using in your answer, is a builtin command of some shells. Not readlink which isn't builtin and is instead a standard POSIX-defined tool. That means that the behavior of realpath can vary depending on the shell used. – terdon Mar 14 '17 at 17:42
  • 1
    @George Yes, because options are different there. See : paste.ubuntu.com/24177730 It's not a big deal, considering that dash and bash are the only shells present in default Ubuntu. It's just a caution, which should be mentioned – Sergiy Kolodyazhnyy Mar 14 '17 at 17:43

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