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

terdon
  • 100,812
Anon
  • 12,063
  • 23
  • 70
  • 124
  • 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. – Anon Mar 14 '17 at 17:46
  • @Akiva if your file names have single quotes in them, then the spaces are the least of your concerns. The quotes will already break whatever you are trying to do. But please come into chat and we can discuss this. – terdon Mar 14 '17 at 17:49
  • Please give an example – George Udosen Mar 14 '17 at 17:50
  • 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
  • @Serg Agreed. Talked to terdon, and i'll start a new question later. Sorry again for the edit. – Anon Mar 14 '17 at 18:05
  • 1
    Try my update and let me know if it flies – George Udosen Mar 14 '17 at 18:17
  • @George I have to apologize for editing my question halfway through; the escaping aspect deserves a question in itself, so that is what I am doing. I'll ping you when I'm done. – Anon Mar 14 '17 at 18:26

3 Answers3

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
Anon
  • 12,063
  • 23
  • 70
  • 124
Sergiy Kolodyazhnyy
  • 105,154
  • 20
  • 279
  • 497
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")"
Zanna
  • 70,465
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.
George Udosen
  • 36,677
  • Can you break down some of that syntax? Particularly [[ -e "$1" ]]? – Anon Mar 14 '17 at 17:23
  • @CharlesDuffy No, he's using realpath, not readlink – Anon Mar 14 '17 at 17:24
  • 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 : http://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