找到当前路径的深度

5

如何编写一个shell脚本来查找当前路径的深度?

假设我在以下目录中:

/home/user/test/test1/test2/test3

应该返回6。

1
提示:使用“字符串分割”和“计数”功能 - glenn jackman
3
为什么你要同时添加“bash”和“fish”这两个标签? 这两个 shell 不支持相同的语法。你的问题过于宽泛。 - Kurtis Rader
Kurtis,感谢您的参与。我在网上搜索了一下,甚至在bash中也找不到这样的脚本。考虑到fish是相对较新的,我并没有期望会有很多回应,所以我愿意获取一个bash脚本并尝试自己转换它。这是我的理性判断。如果这样做是错误的,请原谅我。我能否删除一个标签?我会检查一下。 - SFbay007
好的,现在你删除了 [tag:bash] 标签... 隐式地使那些特定于 Bash 的答案无效。 - Benjamin W.
Banjamin,我非常感谢你的撰写和提出的解决方案。我不知道从帖子中删除标签会产生这样的影响。即使在bash中也没有提出解决深度问题的问题,因此我重新安装了标签,因为您的答案对于对bash感兴趣的人具有很大的价值。谢谢。 - SFbay007
7个回答

8

使用 shell 参数扩展,无需使用外部命令:

$ var=${PWD//[!\/]}
$ echo ${#var}
6

第一个扩展删除所有不是 / 的字符;第二个扩展打印出 var 的长度。
详细解释支持 POSIX shell 或者 Bash(括号中的链接指向相应的 POSIX 标准或 Bash 手册):
  • $PWD 包含当前工作目录的路径。(sh/Bash)
  • ${parameter/pattern/string} 扩展将 parameter 中第一次出现的 pattern 替换为 string(Bash)
    • 如果第一个斜杠是双倍的(如我们的情况),则会替换所有匹配项。
    • 如果 string 为空,则 pattern 后面的斜杠是可选的(如我们的情况)。
  • 模式 [!\/] 是一个括号表达式,表示“除斜杠外的任何字符”。(sh/Bash)
    • 斜杠必须转义为 \/,否则它将被解释为结束模式。
    • 括号表达式中的第一个字符为 ! 表示否定该表达式:除了表达式中的字符外,任何字符都匹配该模式。POSIX sh 要求支持 ! 并且指出使用 ^ 的行为未定义;Bash 支持 !^。请注意,这不是正则表达式中看到的括号表达式,其中只有 ^ 是有效的。
  • ${#parameter} 扩展为 parameter 的长度。(sh/Bash)

1
请问您能解释一下 [!\/] 吗?我不太了解这种情况下的 !。最简洁的方式加1分 :) 也许您可以补充一下哪些 shell 可以执行此操作。 - Gilles Quénot
2
@GillesQuenot 在 shell 模式方括号表达式中,! 作为否定字符是 POSIX 所要求的,而 ^ 的行为是未定义的;Bash 支持 !^。我会添加更多信息。 - Benjamin W.

5
在fish中的简单方法:
count (string split / $PWD)

3
您可以计算当前路径中斜杠的数量:
pwd | awk -F"/" '{print NF-1}'

2

您可以使用管道来完成这个操作。将字符串输入grep,并使用-o选项。这会将每个“/”打印到新行上。再次使用管道将其输入到wc -l中,以计算打印的行数。

echo "$path_str" | grep -o '/' - | wc -l

我喜欢这个,因为它可以在像 ash/dash 这样的最小 shell 中工作。不过,你应该引用 $path_str,否则如果你的字符串包含 Globbing 字符,就可能会遇到令人讨厌的意外情况。顺便说一下,POSIX 要求 $PWD,所以你可以使用它。 - Benjamin W.
引用的观点很好。您能否澄清POSIX是否需要$PWD?恐怕我还没有丰富的Linux经验。 - Alec Xu
不必使用$path_str,你需要为其分配当前路径。你可以使用环境变量$PWD,如果一个shell想要符合POSIX标准,那么这个变量是必须存在的,因为它是一个兼容性标准。 - Benjamin W.

1
假设您没有尾随的斜杠“/”,您只需计算“/”即可。

所以您需要:

  • 删除除“/”以外的所有内容

  • 计算结果字符串的长度

在fish中,可以使用以下代码完成此操作:

string replace --regex --all '[^/]' '' -- $PWD | string length

正则表达式 - [^/] 匹配除了 "/" 以外的任何字符。使用 "--all",这将尽可能多地进行匹配,并用 '' 替换,即什么也不做。

-- 是选项分隔符,以便不将参数中的任何内容解释为选项(否则如果参数以 "-a" 开头,则会出现问题)。

$PWD 是当前目录。

string length 只是输出其输入的长度。


谢谢。如果我想要将计数保存在一个变量中,以便稍后检查,我该如何将输出的长度设置为数字(而不是字符串)?这个命令可以吗?"set length string replace --regex --all '[^/]' '' -- $PWD" 然后稍后我可以执行 "if test $length -lt 7"。 - SFbay007
"string length" 将其转换为数字,因此您可以将其放入变量中并稍后使用。 set length(string replace --regex --all '[^/]' '' -- $PWD | string length); if test $length -lt 7 - faho

0

使用:

echo '/home/user/test/test1/test2/test3' | 
perl -lne '@_ = split /\//; print scalar @_ -1'

输出

6

0
你可以像这样使用 find
find / -printf "%d %p\n" 2>/dev/null | grep "$PWD$" | awk '{print $1}'

可能不是最高效的方法,但能很好地处理斜杠。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接