$ {arg ##/*/}和{} \的含义是什么?在shell脚本中

use*_*194 0 shell sh

请在下面找到代码,以显示当前文件夹中的目录.

  1. ${arg##/*/}shell脚本的含义是什么?(这两个arg#*arg##/*/给出相同的输出).
  2. {} \;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)

mkl*_*nt0 7

添加到@ 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)

请注意,我使用的是basenamedirname这里的解析,因为他们忽略方便终端/的水珠**/不约而同地增加了它的匹配.


findwhile循环中重新处理输出的输出:如果您的文件名包含嵌入的\n字符,则可以使用null char解析如下.分开项目(参见评论为什么-d $'\0'而不是-d ''使用):

find . -type d -print0 | while read -d $'\0' -r arg; ...
Run Code Online (Sandbox Code Playgroud)