Bash 脚本用于查找包含特定子文件夹的文件夹,然后复制到新目录并保留父名称

Bash 脚本用于查找包含特定子文件夹的文件夹,然后复制到新目录并保留父名称

我会尽量具体。我有一个Packages文件夹,里面有各种名称的子文件夹,但每个子文件夹中总会有一个dist文件夹。我想找到包含的文件夹dist,然后移动/复制仅有的 dist及其父文件夹复制到新目录。

例子:

当前路径结构如下:

~/Documents/Packages/core-types/dist
~/Documents/Packages/graphql-utils/dist
~/Documents/Packages/manuscript-assets/dist

注意:core-typesgraphql等除了 之外都包含子文件夹dist;否则这会更简单......

我正在尝试进行设置,以便当这些路径迁移到新目录时,~/Documents/Artifacts/它将看起来像:

~/Documents/Artifacts/core-types/dist
~/Documents/Artifacts/graphql-utils/dist
~/Documents/Artifacts/manuscript-assets/dist

以下是我编写的脚本,希望有人能提供指导:

#!/bin/bash
find ~/Documents/Packages -name dist -print \
| sort -u \
      | while read olddir
        do 
          moveto="~/Documents/Artifacts/$(echo \"$olddir\" | cut -d\/ -f 6)"
          mv "$olddir" "$moveto"
        done

一定有更好的方法来实现这一点......

答案1

我并不是想轻率,但你有两个问题:

  1. 识别名为的子目录dist,以及
  2. 将它们移动或复制到Artifacts目录中。

如果我们使用相对路径名,这会容易得多。如果你确实需要使用绝对路径名(哈哈),那就这么说吧。

以下是执行步骤 1(识别名为 的子目录 dist)的两种方法:

find

#!/bin/sh
cd ~/Documents/Packages &&
find . -name dist -type d -exec sh -c 'for d do parent="${d%/*}"; \
                                                mkdir -p "../Artifacts/$parent"; \
                                                mv "$d" "../Artifacts/$parent"; done' \
                                                sh {} +

find如果需要,您可以将所有命令放在一行上。)这将进入~/Documents/Packages,因此我们可以使用相对路径名。相当直接地使用-name和 的-type测试 find来识别名为 的(子)目录 dist。使用-exec操作将它们的名称传递给微型 shell 脚本。

/该脚本循环遍历其参数。对于每个参数,它通过从右侧删除和路径名级别来标识父目录。例如,的父级./core-types/dist 是 ./core-types。(记住;我们是 ~/Documents/Packages并看着.,所以我们看到的是相对路径名。)我本来可以说parent="${d%/dist}",但我想让它保持通用。创建目标/父目录 — 例如../Artifacts/./core-types。(额外的./被忽略;/./作用类似于/,因此这将创建../Artifacts/core-types,即~/Documents/Packages/../Artifacts/core-types,即~/Documents/Artifacts/core-types。)然后我们将dist目录移动到该目录中。

bash 路径名扩展

这取决于 bash 的一个特性,该特性并不是在所有 shell 中都存在的。(事实上,它可能不在全部版本的 bash。

#!/bin/bash
cd ~/Documents/Packages && shopt -s globstar &&
for d in **/dist/; do d="${d%/}"; parent="${d%/*}";
                                  mkdir -p "../Artifacts/$parent";
                                  mv "$d" "../Artifacts/$parent"; done

设置globstarshell 选项 ( shopt),这将导致**进行递归搜索。然后循环遍历**/dist/。如果我们说**/dist,这将找到所有文件和名为 的目录dist/在末尾添加 将搜索限制在(子)目录中。对于每个目录,执行一组命令。

**/dist/以格式给出目录名称(末尾  core-types/dist/ 带有,正如我们指定的那样)。删除尾部斜杠。其余代码相同。/d="${d%/}"

注意:这不会查找名称以 开头的顶级目录.(例如 ~/Documents/Packages/.memories/dist),除非您添加该dotglob选项。

第2步

如果您想要复制而不是移动,只需在上述任一命令中更改mv为。cp -R

答案2

不确定您是否尝试使用 if (cat /Documents/package/**/*/dist) then mv 或 cp

相关内容