How to retrieve absolute path given relative
use:
find "$(pwd)"/ -type f
to get all files or
echo "$(pwd)/$line"
to display full path (if relative path matters to)
How to obtain the absolute path of a file via Shell (BASH/ZSH/SH)?
Use realpath
$ realpath example.txt
/home/username/example.txt
Reliable way for a Bash script to get the full path to itself
Here's what I've come up with (edit: plus some tweaks provided by sfstewman, levigroker, Kyle Strand, and Rob Kennedy), that seems to mostly fit my "better" criteria:
SCRIPTPATH="$( cd -- "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )"
That SCRIPTPATH
line seems particularly roundabout, but we need it rather than SCRIPTPATH=`pwd`
in order to properly handle spaces and symlinks.
The inclusion of output redirection (>/dev/null 2>&1
) handles the rare(?) case where cd
might produce output that would interfere with the surrounding $( ... )
capture. (Such as cd
being overridden to also ls
a directory after switching to it.)
Note also that esoteric situations, such as executing a script that isn't coming from a file in an accessible file system at all (which is perfectly possible), is not catered to there (or in any of the other answers I've seen).
The --
after cd
and before "$0"
are in case the directory starts with a -
.
finding an absolute path from a supplied path in bash
The ${varname:-default}
notation means "substitute the value of the variable named varname
, if it's set and non-empty; otherwise, substitute the string default
".
In your case, "$( cd "$(dirname ${OUTP})" && pwd)"
is not the name of a variable, so ${"$( cd "$(dirname ${OUTP})" && pwd)":-"/home/default/output/dir"}
is not using the above notation; it's just gibberish.
Also, the dirname
call doesn't make sense to me; I think you might be misunderstanding what that utility does.
Overall, I think what you want is:
OUTPUT_PATH="$(cd "${OUTP:-/home/default/output/dir}" && pwd)"
You'll also want some error-checking afterward, to ensure that $OUTPUT_PATH
is actually set (i.e., that cd
was able to move to the specified directory).
Expanding a relative path to a full path when running a C program in shell
Your question is not very well worded so I am not sure I am answering the same question that you are asking, but you can convert "./myScript" to its full path using the realpath() function.
How do you normalize a file path in Bash?
if you're wanting to chomp part of a filename from the path, "dirname" and "basename" are your friends, and "realpath" is handy too.
dirname /foo/bar/baz
# /foo/bar
basename /foo/bar/baz
# baz
dirname $( dirname /foo/bar/baz )
# /foo
realpath ../foo
# ../foo: No such file or directory
realpath /tmp/../tmp/../tmp
# /tmp
realpath
alternatives
If realpath
is not supported by your shell, you can try
readlink -f /path/here/..
Also
readlink -m /path/there/../../
Works the same as
realpath -s /path/here/../../
in that the path doesn't need to exist to be normalized.
Find absolute path in shell script run by superuser for a path given by regular user. Resolve paths stored in variables to absolute paths portably
Note: The OP's problem is ultimately unrelated to the fact that the script is run with sudo
(as superuser), because ~
and $HOME
by default still reflect the real user's home dir when running with sudo
- unless you use sudo -H
.
The primary problem is that the input path (stored in
$REL_PATH
) starts with a literal~
(due to being part of a double-quoted string), whereas the shell only applies tilde expansion to unquoted~
instances at the beginning of the word.However, the
~
must be quoted in$REL_PATH
so as to defer expansion until the path should be determined in the context of the user running the script.- Note that the OP wants to support both
~
(current user's home dir.) and~<username>
expansions (<username>
's home dir.)
- Note that the OP wants to support both
It is therefore tempting to simply pass $REL_PATH
to eval
as a whole, but that is not only risky1, but is likely to break with paths containing shell metacharacters such as &
and have leading or trailing whitespace or contain run of two or more spaces.
Therefore, the following, POSIX-compliant solution:
- isolates the
~
token at the beginning of a path and expands just it, usingeval
safely, - then puts the path back together by appending the rest of the path to the expanded token.
#!/bin/sh
# Note: Assumes that:
# * $REL_PATH is set to the input path.
# * $user is set to the real username.
case $REL_PATH in
\~|\~/*) # a ~ or ~/... path, expand the ~ based on the real user.
# NOTE: If you know that `sudo` is never invoked with `-H`,
# you could simply use `$HOME` instead of `$(eval "echo ~$user")`.
ABS_PATH="$(eval "echo ~$user")${REL_PATH#\~}"
;;
\~*) # a ~<username> or ~<username>/... path; expand the ~<username> part.
otherUserHomeDirRef=${REL_PATH%%/*}
# Make sure that $otherUserHomeDirRef is a well-formed
# ~/<username> token, so that `eval` can be safely applied.
if ! expr "$otherUserHomeDirRef" : '~[a-zA-Z0-9][a-zA-Z0-9._-]*$' >/dev/null; then
echo "ERROR: Malformed input path: $REL_PATH" 1>&2
exit 2
fi
otherUserHomeDir=$(eval echo "$otherUserHomeDirRef")
if [ "$otherUserHomeDirRef" = "$REL_PATH" ]; then
ABS_PATH=$otherUserHomeDir
else
ABS_PATH="$otherUserHomeDir/${REL_PATH#*/}"
fi
;;
/*) # already an absolute path, use as-is
ABS_PATH=$REL_PATH
;;
*) # a relative path, resolve based on *current* dir
ABS_PATH="$PWD/$REL_PATH"
esac
# Print the absolute path.
printf '%s\n' "$ABS_PATH"
- Only POSIX-compliant parameter expansions are used.
- POSIX-utility
expr
is used for regex matching. - Use of
eval
is safe here, because the input is either known to be safe or explicitly checked beforehand. - The resulting absolute path is, per the OP's requirements:
- not normalized; that is, components such as
.
and..
are retained. - not checked for existence.
- not normalized; that is, components such as
Note that it's generally not a good idea to use all-uppercase variable names such as ABS_PATH
, because they can conflict with special shell and environment variables.
[1] Of course, the greater risk in the OP's script is the sourcing of the config file, which could contain any shell code.
Related Topics
How to Read Ring Buffer Within Linux Kernel Space
Expand a Possible Relative Path in Bash
Architecture of I386 Input File Is Incompatible with I386:X86-64
How to Get the Nvidia Driver Version from the Command Line
Magic Numbers of the Linux Reboot() System Call
Automating Amazon Ebs Snapshots Anyone Have a Good Script or Solution for This on Linux
Number of Processors/Cores in Command Line
Fuse Error: Transport Endpoint Is Not Connected
How to Convert a PDF into Jpg with Command Line in Linux
Count Occurrences of Character Per Line/Field on Unix
How to Prepend a Directory the Library Path When Loading a Core File in Gdb on Linux
How to Concatenate Two Strings to Build a Complete Path
Determine Target Isa Extensions of Binary File in Linux (Library or Executable)
How Can Objdump Emit Intel Syntax
What Are Meanings of Fields in /Proc/Net/Dev
How to Create Web Based Terminal Using Xterm.Js to Ssh into a System on Local Network