例如检查是否$PWD
是/home 的子目录。换句话说,我正在搜索 bash 字符串操作来检查一个字符串是否以另一个字符串开头。
答案1
要在任何 Bourne 风格的 shell 中测试一个字符串是否是另一个字符串的前缀:
case $PWD/ in
/home/*) echo "home sweet home";;
*) echo "away from home";;
esac
同样的原理也适用于后缀或子字符串测试。请注意case
,与文件名不同,在构造中*
匹配任何字符,包括 a/
或首字母.
.
在实现该语法的 shell [[ … ]]
(即 bash、ksh 和 zsh)中,它可用于将字符串与模式进行匹配。 (请注意,该[
命令只能测试字符串是否相等。)
if [[ $PWD/ = /home/* ]]; then …
如果您专门测试当前目录是否在下面/home
,则由于符号链接的存在,简单的子字符串测试是不够的。
如果/home
是它自己的文件系统,则测试当前目录 ( .
) 是否位于该文件系统上。
if [ "$(df -P . | awk 'NR==2 {print $6}')" = "/home" ]; then
echo 'The current directory is on the /home filesystem'
fi
如果您有 NetBSD、OpenBSD 或 GNU 或 busybox 或 toybox readlink
(最后 3 个常见于基于 Linux 的系统,如 Debian、OpenWrt 或 Android),您可以使用readlink -f
从路径中删除符号链接。
case $(readlink -f .)/ in "$(readlink -f /home)"/*) …
有些系统也有一个realpath
命令(也在 GNU 工具箱中,现在它是首选readlink
):
case $(realpath .)/ in "$(realpath /home)"/*) …
shellzsh
也有自己的realpath()
带有:P
修饰符的运算符:
if () [[ $1:P/ = $2:P/* ]] . /home; then …
否则,您可以使用pwd
显示当前目录。但是,如果您的 shell 跟踪cd
命令并保留用于访问目录的名称而不是其“实际”位置,则必须注意不要使用内置 shell 。
case $(pwd -P 2>/dev/null || env PWD= pwd)/ in
"$(cd /home && { pwd -P 2>/dev/null || env PWD= pwd; })"/*) …
答案2
如果您想可靠地测试一个目录是否是另一个目录的子目录,您需要的不仅仅是字符串前缀检查。吉尔斯的回答详细描述了如何正确进行此测试。
但如果您确实想要一个简单的字符串前缀检查(也许您已经规范化了路径?),这是一个很好的选择:
test "${PWD##/home/}" != "${PWD}"
如果$PWD
以“/home/”开头,它会在左侧被剥离,这意味着它不会与右侧匹配,因此“!=”返回 true。
答案3
粗制版:
[ "${PWD:0:6}" = /home/ ]
缺点是必须先计算字符数,并且不能/home/
用诸如 之类的通用内容替换$1
。
编辑(感谢@Michael)进行概括以与$VAR
可以使用的进行比较
[ "${PWD:0:${#VAR}}" = "$VAR" ]
答案4
我不太明白这个问题,但要找到的父母$PWD, 做dirname -- "$PWD"
。要查找父级的父级,请运行dirname -- "$(dirname -- "$PWD")"
,等等......