在bash中展开相对路径
1.概述
在本教程中,我们将了解在 bash 中扩展相对路径的各种方法。
2. 绝对路径和相对路径的区别
在 Linux 中,路径用于引用目录或文件。我们指定从文件系统的根到最终目的地的完整路径,使用第一个斜杠 ( / ) 作为根,后面的斜杠作为分隔符:
/etc/ssl/certs
/usr/bin/ls
/usr/lib/libssl.so.3
**但是,对于相对路径,我们以文件或目录名称而不是斜杠开始路径。**这意味着它们是相对于当前目录的:
file.txt
./file.txt
../../usr/bin/ls
让我们通过一个例子更清楚地理解这一点。假设我们在目录*/tmp/files中,我们在其中创建了一个名为file1的文件。现在,我们可以在该特定目录中使用路径file1或./file1*访问该文件,但不能从其他任何地方访问:
$ cd /tmp/files/
$ touch file1
$ ls ./file1
./file1
$ cd /tmp/
$ ls ./file1
ls: ./file1: No such file or directory
由于我们使用的是相对路径,因此我们无法从其他目录访问该文件。因此,我们可以从任何地方通过绝对路径访问文件,而相对路径取决于当前目录。
我们使用单点和双点 分别表示当前目录和父目录。**我们可以使用多个双点来继续向上的目录结构。*假设我们要创建从主目录到/etc/passwd*文件的相对路径:
$ pwd
/home/blogdemo
$ cat ../../etc/passwd
root:x:0:0:root:/root:/bin/sh
...
通过两个双点,我们到达*/从/home/blogdemo。*
3. 解析相对路径
我们可能需要在各种情况下解析相对路径,例如将它们传递给需要绝对路径的程序。
3.1.使用 Bash 内置函数
我们可以创建一个 bash 函数,该函数利用基本的 bash 内置函数(如pwd和变量替换)来实现我们的目的。这避免了调用外部进程的开销:
resolve_relative_path() (
# If the path is a directory, we just need to 'cd' into it and print the new path.
if [ -d "$1" ]; then
cd "$1" || return 1
pwd
# If the path points to anything else, like a file or FIFO
elif [ -e "$1" ]; then
# Strip '/file' from '/dir/file'
# We only change the directory if the name doesn't match for the cases where
# we were passed something like 'file' without './'
if [ ! "${1%/*}" = "$1" ]; then
cd "${1%/*}" || return 1
fi
# Strip all leading slashes upto the filename
echo "$(pwd)/${1##*/}"
else
return 1 # Failure, neither file nor directory exists.
fi
)
我们必须将函数包裹在方括号而不是花括号中,以便它在子 shell 中运行并在退出时恢复原始工作目录。
请注意pwd默认不解析符号链接,所以如果我们在*/tmp/symlinked_dir中,它是/tmp/original_dir的符号链接,那么pwd将只打印/tmp/symlinked_dir*。我们可以使用*-P*标志来解析目录符号链接。但是,此函数仍无法解析文件符号链接。
让我们用几个参数来测试这个函数:
$ pwd
/tmp/test
$ ls
directory file1
$ resolve_relative_path file1
/tmp/test/file1
$ resolve_relative_path ..
/tmp
$ resolve_relative_path ../test/directory
/tmp/test/directory
$ resolve_relative_path /usr/lib/../bin/..
/usr
3.2. 使用readlink
我们可以使用readlink 命令来解析相对路径,包括符号链接。它使用-f*标志打印完整路径*:
$ readlink -f /usr/../tmp/link
/tmp/real
这里 /tmp/link是 /tmp/real文件的符号链接。
readlink -f仅在使用不存在的目录调用它时返回非零退出代码,但如果文件的目录存在则返回零。因此,readlink -f /tmp/non-existent将返回 0,但readlink -f /non-existent-dir/non-existent-file将返回 1
3.3. 使用realpath
最后,我们有realpath 命令,其行为类似于readlink -f:
$ realpath /tmp/non-existent; echo $?
/tmp/non-existent
0
$ realpath /non-existent-dir/non-existent-file; echo $?
realpath: /non-existent-dir: No such file or directory
1
$ realpath /tmp/link
/tmp/real