问题:是否有一个简单的sh/bash/zsh/fish/...命令来打印我提供的文件的绝对路径?
用例:我在目录中/a/b,我想c在命令行上打印文件的完整路径,以便我可以轻松地将其粘贴到另一个程序中:/a/b/c.简单但是一个小程序可以在处理长路径时节省大约5秒钟,这最终会增加.因此,令我惊讶的是,我无法找到标准实用程序来执行此操作 - 真的没有吗?
这是一个示例实现,abspath.py:
#!/usr/bin/python
# Author: Diggory Hardy <diggory.hardy@gmail.com>
# Licence: public domain
# Purpose: print the absolute path of all input paths
import sys
import os.path
if len(sys.argv)>1:
for i in range(1,len(sys.argv)):
print os.path.abspath( sys.argv[i] )
sys.exit(0)
else:
print >> sys.stderr, "Usage: ",sys.argv[0]," PATH."
sys.exit(1)
Run Code Online (Sandbox Code Playgroud)
Ben*_*ier 490
试试realpath.
$ realpath example.txt
/home/username/example.txt
Run Code Online (Sandbox Code Playgroud)
Pau*_*ce. 301
尝试readlink解决符号链接:
readlink -e /foo/bar/baz
Run Code Online (Sandbox Code Playgroud)
dog*_*ane 240
#! /bin/sh
echo "$(cd "$(dirname "$1")"; pwd -P)/$(basename "$1")"
Run Code Online (Sandbox Code Playgroud)
pet*_*erh 78
忘掉readlink和realpath可能会或可能不会被你的系统上安装.
在这里扩展了dogbane的答案,它被表达为一个函数:
#!/bin/bash
get_abs_filename() {
# $1 : relative filename
echo "$(cd "$(dirname "$1")" && pwd)/$(basename "$1")"
}
Run Code Online (Sandbox Code Playgroud)
你可以像这样使用它:
myabsfile=$(get_abs_filename "../../foo/bar/file.txt")
Run Code Online (Sandbox Code Playgroud)
该解决方案利用了这样一个事实:pwd当没有参数调用时,Bash内置命令将打印当前目录的绝对路径.
它是便携式的,不需要也不readlink或realpath经常不上的默认安装中存在一个给定的Linux/Unix发行版.
如上所述,如果给定的目录路径不存在,函数将失败并在stderr上打印.这可能不是你想要的.您可以扩展该功能以处理这种情况:
#!/bin/bash
get_abs_filename() {
# $1 : relative filename
if [ -d "$(dirname "$1")" ]; then
echo "$(cd "$(dirname "$1")" && pwd)/$(basename "$1")"
fi
}
Run Code Online (Sandbox Code Playgroud)
现在,如果父目录不存在,它将返回一个空字符串.
嗯,在这种情况下确实给出了绝对路径,但不是最小路径.它看起来像:
/Users/bob/Documents/..
Run Code Online (Sandbox Code Playgroud)
如果你想解决'..',你需要使脚本像:
get_abs_filename() {
# $1 : relative filename
filename=$1
parentdir=$(dirname "${filename}")
if [ -d "${filename}" ]; then
echo "$(cd "${filename}" && pwd)"
elif [ -d "${parentdir}" ]; then
echo "$(cd "${parentdir}" && pwd)/$(basename "${filename}")"
fi
}
Run Code Online (Sandbox Code Playgroud)
Fli*_*imm 75
$ readlink -m FILE
/path/to/FILE
Run Code Online (Sandbox Code Playgroud)
这比readlink -e FILEor好realpath,因为即使文件不存在也能正常工作.
Ale*_*hek 64
这个绝对路径转换器shell函数的相对路径
cd和pwd)..和.码:
function abspath() {
# generate absolute path from relative path
# $1 : relative filename
# return : absolute path
if [ -d "$1" ]; then
# dir
(cd "$1"; pwd)
elif [ -f "$1" ]; then
# file
if [[ $1 = /* ]]; then
echo "$1"
elif [[ $1 == */* ]]; then
echo "$(cd "${1%/*}"; pwd)/${1##*/}"
else
echo "$(pwd)/$1"
fi
fi
}
Run Code Online (Sandbox Code Playgroud)
样品:
# assume inside /parent/cur
abspath file.txt => /parent/cur/file.txt
abspath . => /parent/cur
abspath .. => /parent
abspath ../dir/file.txt => /parent/dir/file.txt
abspath ../dir/../dir => /parent/dir # anything cd can handle
abspath doesnotexist => # empty result if file/dir does not exist
abspath /file.txt => /file.txt # handle absolute path input
Run Code Online (Sandbox Code Playgroud)
注意:这是基于nolan6000和bsingh的答案,但修复了文件大小写.
我也理解原始问题是关于现有的命令行实用程序.但是因为这似乎是stackoverflow的问题,包括想要具有最小依赖性的shell脚本,我把这个脚本解决方案放在这里,所以我可以在以后找到它:)
les*_*eal 23
该find命令可能有所帮助
find $PWD -name ex*
find $PWD -name example.log
Run Code Online (Sandbox Code Playgroud)
列出当前目录中或下面的所有文件,其名称与模式匹配.如果您只获得一些结果(例如,包含少量文件的树底部附近的目录),您可以简化它
find $PWD
Run Code Online (Sandbox Code Playgroud)
我在Solaris 10上使用它,它没有提到的其他实用程序.
hlu*_*luk 15
如果你没有readlink或realpath实用程序,你可以使用在bash和zsh中工作的以下函数(不确定其余部分).
abspath () { case "$1" in /*)printf "%s\n" "$1";; *)printf "%s\n" "$PWD/$1";; esac; }
Run Code Online (Sandbox Code Playgroud)
这也适用于不存在的文件(与python函数一样os.path.abspath).
不幸的abspath ./../somefile是没有摆脱点.
这是一个zsh-only函数,我喜欢它的紧凑性.它使用'A'扩展修饰符 - 参见zshexpn(1).
realpath() { for f in "$@"; do echo ${f}(:A); done }
Run Code Online (Sandbox Code Playgroud)
一般没有这样的事情的 absolute path一个文件(这个声明意味着,可能有一个以上的一般,因此使用了定冠词的是不恰当的).An absolute path是从根"/"开始的任何路径,并且指定一个没有歧义的文件,独立于工作目录.(例如参见维基百科).
A relative path是从另一个目录开始解释的路径.它可能是工作目录,如果它是relative path由应用程序操纵(虽然不一定).当它在目录中的符号链接中时,通常旨在相对于该目录(尽管用户可能还有其他用途).
因此,绝对路径只是相对于根目录的路径.
路径(绝对路径或相对路径)可能包含也可能不包含符号链接.如果不是这样,它在某种程度上也不受链接结构变化的影响,但这不是必需的,甚至不是必需的.有人叫canonical path(或canonical file name或resolved path)的absolute path其中所有符号链接都得到了解决,即通过向whetever它们链接到的路径已被替换.命令realpath和readlink两者都寻找规范路径,但只有realpath一个选项来获取绝对路径而不必费心解析符号链接(以及其他几个选项来获取各种路径,绝对或相对于某个目录).
这需要几个评论:
realpath并readlink有选项来解释它.canonical.因此,概念是时间(或环境)依赖.canonical path文件可能仍然不止一个,原因有两个:
ro)挂载在几个挂载点上.因此,即使有更严格的定义canonical path,也可能存在一些文件的规范路径.这也意味着限定符canonical有些不足,因为它通常意味着唯一性的概念.
这扩展了对该主题的简短讨论,以回答Bash中的另一个类似问题:检索给定相对的绝对路径
我的结论是,realpath设计更好,更灵活readlink.如果没有选项返回符号链接的值readlink,则不会使用它的唯一用途realpath.
如果您只想使用内置函数,最简单的方法可能是:
find `pwd` -name fileName
Run Code Online (Sandbox Code Playgroud)
只需输入两个额外的单词,这将适用于所有 unix 系统以及 OSX。
在dogbane 回答什么是对未来的描述:
#! /bin/sh
echo "$(cd "$(dirname "$1")"; pwd)/$(basename "$1")"
Run Code Online (Sandbox Code Playgroud)
解释:
"$1"dirname "$1"cd "$(dirname "$1")进入这个相对目录并通过运行pwdshell 命令获取它的绝对路径$(basename "$1")echo就在某些情况下,此问题的最佳答案可能会产生误导。想象一下,您要查找其绝对路径的文件位于$PATH变量中:
# node is in $PATH variable
type -P node
# /home/user/.asdf/shims/node
cd /tmp
touch node # But because there is a file with the same name inside the current dir check out what happens below
readlink -e node
# /tmp/node
readlink -m node
# /tmp/node
readlink -f node
# /tmp/node
echo "$(cd "$(dirname "node")"; pwd -P)/$(basename "node")"
# /tmp/node
realpath node
# /tmp/node
realpath -e node
# /tmp/node
# Now let's say that for some reason node does not exist in current directory
rm node
readlink -e node
# <nothing printed>
readlink -m node
# /tmp/node # Note: /tmp/node does not exist, but is printed
readlink -f node
# /tmp/node # Note: /tmp/node does not exist, but is printed
echo "$(cd "$(dirname "node")"; pwd -P)/$(basename "node")"
# /tmp/node # Note: /tmp/node does not exist, but is printed
realpath node
# /tmp/node # Note: /tmp/node does not exist, but is printed
realpath -e node
# realpath: node: No such file or directory
Run Code Online (Sandbox Code Playgroud)
基于以上内容,我可以得出结论:realpath -e和readlink -e可用于查找我们期望存在于当前目录中的文件的绝对路径,而结果不受$PATH变量的影响。唯一的区别是realpath输出到 stderr,但如果找不到文件,两者都会返回错误代码:
cd /tmp
rm node
realpath -e node ; echo $?
# realpath: node: No such file or directory
# 1
readlink -e node ; echo $?
# 1
Run Code Online (Sandbox Code Playgroud)
现在,如果您想要中存在的文件的绝对路径 a$PATH,则以下命令将是合适的,与当前目录中是否存在同名文件无关。
type -P example.txt
# /path/to/example.txt
# Or if you want to follow links
readlink -e $(type -P example.txt)
# /originalpath/to/example.txt
# If the file you are looking for is an executable (and wrap again through `readlink -e` for following links )
which executablefile
# /opt/bin/executablefile
Run Code Online (Sandbox Code Playgroud)
如果缺少,则回退$PATH,例如:
cd /tmp
touch node
echo $(readlink -e node || type -P node)
# /tmp/node
rm node
echo $(readlink -e node || type -P node)
# /home/user/.asdf/shims/node
Run Code Online (Sandbox Code Playgroud)
realpath是最好的答案,但如果您没有安装它,您必须首先运行brew install coreutils它将安装具有许多很棒功能的coreutils 。编写自定义函数并导出它的工作量太大,而且对于这样的事情存在出错的风险,这里有两行:
$ brew install coreutils
$ realpath your-file-name.json
Run Code Online (Sandbox Code Playgroud)