请找到以下代码,以显示当前文件夹中的目录。
${arg##/*/}
的含义是什么? (arg#*
和arg##/*/
都提供相同的输出。){} \;
的含义是什么。for arg in `find . -type d -exec ls -d {} \;`
do
echo "Output 1" ${arg##/*/}
echo "Output 2" ${arg#*}
done
答案 0 :(得分:7)
添加到@ JoSo的有用答案:
${arg#*}
是从根本上毫无意义的扩展,因为它的结果始终与$arg
本身相同,因为它删除最短前缀匹配< em>任何字符(*
)和匹配任何字符的最短前缀是空字符串。
${arg##/*/}
- 剥离最长的前缀匹配模式/*/
- 在此上下文中无效,因为输出路径为{{1 - 由于使用./
而加前缀,因此没有以find .
开头的前缀。相比之下,/
将工作并剥离父路径(仅保留文件夹名称组件)。
除了ill-advised to parse command output in a for
loop,正如@JoSo指出的那样,
OP中的${arg##*/}
命令过于复杂且效率低下
(另外,为了澄清,find
命令列出了当前文件夹的子树中的所有文件夹,而不仅仅是直接子文件夹):
find
可以简化为:
find . -type d -exec ls -d {} \;
这两个命令的作用相同:find . -type d
完全按照-exec ls -d {} \;
默认执行的操作(隐含的find
)。
如果我们把它们放在一起,我们得到:
-print
请注意,我已使用find . -mindepth 1 -type d | while read -r arg
do
echo "Folder name: ${arg##*/}"
echo "Parent path: ${arg%/*}"
done
作为第二个输出项,它会删除匹配${arg%/*}
的最短后缀,从而返回父级路径;此外,我添加了/*
,以便-mindepth 1
也不匹配find
.
来内联处理shell命令,-exec
一次传递尽可能多的路径:
+
最后,如果你有GNU find . -mindepth 1 -type d -exec /bin/sh -c \
'for arg; do echo "Folder name: ${arg##*/}"; echo "Parent: ${arg%/*}"; done' \
-- {} +
,事情变得更加容易,因为你可以利用find
主数据库,它支持文件名和父路径之类的占位符:
-printf
这是一个基于globbing(路径名扩展)的 bash-only解决方案,由@AdrianFrühwirth提供:
警告:这需要find . -type d -printf 'Folder name: %f\nParen path: %h\n'
,shell选项bash 4+
处于开启状态(globstar
) - 默认情况下处于关闭状态。
shopt -s globstar
请注意,我在这里使用shopt -s globstar # bash 4+ only: turn on support for **
for arg in **/ # process all directories in the entire subtree
do
echo "Folder name: $(basename "$arg")"
echo "Parent path: $(dirname "$arg")"
done
和basename
进行解析,因为它们会方便地忽略glob dirname
总是添加到其匹配项中的终止/
。 / p>
在**/
循环中重新处理find
的输出:如果您的文件名包含嵌入的while
字符,则可以使用null char解析如下。分隔项目(请参阅有关使用\n
而不是-d $'\0'
的原因的评论):
-d ''
答案 1 :(得分:2)
${arg##/*/}
是&#34;参数扩展&#34;的应用程序。 (在shell的手册中搜索这个术语,例如在linux shell中输入man bash
)。它扩展为arg
,没有与/*/
匹配的最长arg前缀作为glob模式。例如。如果arg
为/foo/bar/doo
,则展开为doo
。
那个糟糕的shell代码(类似于Bash Pitfalls上的第1项)。 {} \;
与shell没什么关系,但更多的是find
命令期望-exec
子命令的参数。 {}
将替换为当前文件名,例如这会导致find
执行命令ls -d FILENAME
,并将FILENAME替换为它找到的每个文件。 \;
充当-exec
参数的终止符。请参阅find
的手册页,例如在linux shell上键入man find
,并在那里查找字符串-exec
以查找说明。