请在下面找到代码,以显示当前文件夹中的目录.
${arg##/*/}shell脚本的含义是什么?(这两个arg#*和arg##/*/给出相同的输出).{} \;in for loop语句的含义是什么.for arg in `find . -type d -exec ls -d {} \;`
do
echo "Output 1" ${arg##/*/}
echo "Output 2" ${arg#*}
done
Run Code Online (Sandbox Code Playgroud)
添加到@ JoSo的有用答案:
${arg#*}是根本没有意义的膨胀,作为它的结果总是相同的$arg本身,因为它去除的最短前缀匹配任何字符(*)和最短前缀匹配任何字符是空字符串.
${arg##/*/}- 剥离最长前缀匹配模式/*/- 在此上下文中没用,因为输出路径将./由于使用而被预先定义find .,因此将不会有前缀/.相反,${arg##*/}将工作并剥离父路径(仅保留文件夹名称组件).
除了在for循环中解析命令输出是不明智的,正如@JoSo指出的那样,findOP中的命令过于复杂且效率低下(另外,为了澄清,该find命令列出了当前文件夹子树中的所有文件夹),而不仅仅是直接的子文件夹):
find . -type d -exec ls -d {} \;
Run Code Online (Sandbox Code Playgroud)
可以简化为:
find . -type d
Run Code Online (Sandbox Code Playgroud)
这两个命令做相同的:-exec ls -d {} \;简单地做什么find(默认设置)反正(隐含-print).
如果我们把它们放在一起,我们得到:
find . -mindepth 1 -type d | while read -r arg
do
echo "Folder name: ${arg##*/}"
echo "Parent path: ${arg%/*}"
done
Run Code Online (Sandbox Code Playgroud)
请注意,我用作${arg%/*}第二个输出项,它删除最短的后缀匹配/*,从而返回父路径; 此外,我添加了-mindepth 1这样find也不匹配.
@JoSo在评论中展示了一种更简单,更高效的解决方案; 它用于在线-exec处理shell命令并+一次传递尽可能多的路径:
find . -mindepth 1 -type d -exec /bin/sh -c \
'for arg; do echo "Folder name: ${arg##*/}"; echo "Parent: ${arg%/*}"; done' \
-- {} +
Run Code Online (Sandbox Code Playgroud)
最后,如果你有GNU find,事情变得更加容易,因为你可以利用-printfprimary,它支持文件名和父路径之类的占位符:
find . -type d -printf 'Folder name: %f\nParen path: %h\n'
Run Code Online (Sandbox Code Playgroud)
这是一个基于globbing(路径名扩展)的bash-only解决方案,由@AdrianFrühwirth提供:
警告:这需要bash 4+在shell选项globstar打开(shopt -s globstar)时默认为OFF.
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
Run Code Online (Sandbox Code Playgroud)
请注意,我使用的是basename和dirname这里的解析,因为他们忽略方便终端/的水珠**/不约而同地增加了它的匹配.
find在while循环中重新处理输出的输出:如果您的文件名包含嵌入的\n字符,则可以使用null char解析如下.分开项目(参见评论为什么-d $'\0'而不是-d ''使用):
find . -type d -print0 | while read -d $'\0' -r arg; ...
Run Code Online (Sandbox Code Playgroud)