Answers:
您不需要处理诸如~
shell之类的事情。这就是为什么您可以传递~/filename
给任何脚本或程序并且可以正常工作的原因-所有这些程序都不自行处理~
,您的shell将参数转换为/home/username/filename
并将其传递给程序:
$ echo ~/filename
/home/mrozekma/filename
如果您需要一个规范的文件名(其中不包含..
),请使用realpath
(感谢Neil):
$ realpath ~/../filename
/home/filename
至于将路径分为目录名和文件名,请使用dirname
和basename
:
$ dirname /foo/bar/baz
/foo/bar
$ basename /foo/bar/baz
baz
realpath
更好,但是readlink
当我尝试它时似乎可以工作;您知道失败的例子吗?
cd /tmp; touch foo; ln -s foo bar; cd; readlink /tmp/bar
。这将返回foo
并realpath
返回/tmp/foo
,这就是您想要的。
readlink -f
(note -f
)几乎等同于realpath
,并且更具可移植性:readlink -f
在GNU coreutils中,也存在于其他一些系统上;realpath
单独包装,可能无法安装(例如,在Ubuntu 10.04或Debian lenny中仅依赖5个非常见包装)。
使用Michael提到的dirname和basename应该是获得所需内容的最安全方法。
无论如何,如果您真的想使用“仅打击工具”来执行此操作,则可以使用参数替换:
echo `basename $PWD` # Basename of current working directory.
echo "${PWD##*/}" # Basename of current working directory.
echo
echo `basename $0` # Name of script.
echo $0 # Name of script.
echo "${0##*/}" # Name of script.
echo
filename=test.data
echo "${filename##*.}" # data
# Extension of filename.
该示例直接取自《高级Bash脚本指南》,值得一看。
解释很简单:
$ {var#Pattern}从$ var中删除与$ var前端匹配的$ Pattern最短部分。$ {var ## Pattern}从$ var中删除与$ var前端匹配的$ Pattern中最长的部分。
像一些正则表达式和#
或##
某种贪婪/非贪婪修饰符一样看待模式。
如果您必须对路径部分进行一些更复杂的提取,这可能会很有用。
${...##...}
和朋友,而不是dirname
和basename
他们不适用于所有情况。例如两者${0##*/}
并${0%/*}
扩大到一样$0
,如果$0
不包含/
。
${0%/*}
不是一个很好的选择dirname
。但是,使用${0##*/}
代替代替有basename
什么问题?
$0
是带有尾随的目录名称/
。但是我后悔我的建议,因为dirname
情况没有任何改善。
realpath
是一个告诉您实际路径的命令(删除..和符号链接等)
这是FreeBSD的标准配置。根据此讨论,它也可用于Linux:
http://www.unix.com/shell-programming-scripting/89294-geting-real-path.html
该讨论还提供了一个bash解决方案:
$ bash -c "cd /foo/../bar/ ; pwd"