如何使用命令行在最后一个目录中递归创建一个目录?

kin*_*986 5 command-line directory mkdir

假设我有以下目录结构,其中目录的名称无关紧要:

currentDir/
   Dir1
      Dir1
         Dir1 *
      Dir2 *
      Dir3 *
   Dir2
      Dir1 *
      Dir2 
         Dir1*
   Dir3*
Run Code Online (Sandbox Code Playgroud)

有没有一种方法可以只在树枝末端的目录中创建一个名为“Texture”的目录(在示例中它们用 标记*)。我想让它只让那些目录得到一个Texture目录,而不是任何其他目录。

所有目录可能有也可能没有文件,但最终目录中不会有任何其他目录。

Zan*_*nna 6

首先开启递归通配

shopt -s globstar
Run Code Online (Sandbox Code Playgroud)

现在我们可以查看所有目录**。要取消设置,您可以使用shopt -u globstar(默认情况下它是关闭的,因此当您打开新外壳时它会关闭)。

在以下所有内容中,echo在测试后删除以实际创建目录。

如果树尾目录为空,您可以测试是否为空,并仅在检测到目录时才创建该目录......类似

for d in **/; do [[ -z "$(ls -Aq "$d")" ]] && echo mkdir "$d"Texture; done
Run Code Online (Sandbox Code Playgroud)

即如果输出ls -A (hidden files except current and parent dir) -q (printing ? for non-printing characters)为空,则创建一个目录。

但是由于目录包含文件,我们最好测试一下没有目录

for d in **/; do [[ -z "$(find "$d" -maxdepth 1 -mindepth 1 -type d)" ]] && echo mkdir "$d"Texture; done
Run Code Online (Sandbox Code Playgroud)

mindepth -1是停止找到当前目录...find看到隐藏文件,所以我们知道这些文件被包含在内。由于任何字符都应该通过测试(我们只想检查输出是否为空),这应该是相当安全的......

一种更简洁的方式(对不起 Greg)(但实际上所有这些方法都做了类似的事情 - 我们可以避免使用文件名作为文本,因为我们实际上并没有在这里尝试对这些文件本身做任何事情):

for d in **/; do (ls -Alq "$d" | grep -q '^d') || echo mkdir "$d"Textures; done
Run Code Online (Sandbox Code Playgroud)

在这里我们添加了-l长输出的标志,它打印表单中的每个文件

drwxrwxr-x 5 zanna zanna 4096 Sep 27 22:00 Dir1
Run Code Online (Sandbox Code Playgroud)

然后我们将这些东西吞入管道grep以查看是否有任何行开头d(意味着有一个目录)。我们不想grep打印任何无意义的不可靠文本,所以我们只是检查它的退出状态,-q看看它是否找到了任何东西。如果没有,我们创建一个目录(使用||or 操作符,意思是,如果上一个失败,则执行下一个命令)。实际上,即使您的文件名包含可怕的字符(例如换行符),这也应该有效,因为将ls它们打印为?- 每行都应以指示文件类型的字母开头,因此,可能没有小猫会死。

  • `$()` 引入了一个子shell,因此嵌套的双引号根本不会相互交互。 (2认同)

gle*_*man 5

这是一个痛苦的find -exec电话

前:

$ tree currentDir
currentDir
??? Dir1
?   ??? Dir1
?   ?   ??? Dir1
?   ??? Dir2
?   ??? Dir3
??? Dir2
?   ??? Dir1
?   ??? Dir2
?       ??? Dir1
??? Dir3
Run Code Online (Sandbox Code Playgroud)

创建纹理目录

$ find currentDir -depth -type d -exec bash -c 'cd "$1"; shopt -s globstar nullglob; texture=(**/Texture); [[ ${#texture[@]} -eq 0 ]] && mkdir Texture' _ '{}' \;
Run Code Online (Sandbox Code Playgroud)

这取决于:

  • find-depth启用深度优先导航的选项
  • bash 的globstarshell 选项来启用递归文件模式匹配
  • 请注意_参数:进入 bash var$0以便 find 的当前路径名可以是 bash var$1

$ tree currentDir
currentDir
??? Dir1
?   ??? Dir1
?   ?   ??? Dir1
?   ?       ??? Texture
?   ??? Dir2
?   ?   ??? Texture
?   ??? Dir3
?       ??? Texture
??? Dir2
?   ??? Dir1
?   ?   ??? Texture
?   ??? Dir2
?       ??? Dir1
?           ??? Texture
??? Dir3
    ??? Texture
Run Code Online (Sandbox Code Playgroud)