【问题标题】:Bash script to copy a directory from multiple subdirectories with directory structure用于从具有目录结构的多个子目录中复制目录的 Bash 脚本
【发布时间】:2022-01-12 14:10:29
【问题描述】:

Shell 脚本的新手,必须将类文件从不同的子目录复制到另一个目标目录 我的目录结构是

Module
    |-- submodule
    |         |--main
    |         |--test
    |         |--target
    |               |__classes
    |               |__src  
    |
    |
    |-- subdirectory
              |--maintest
              |--target
                    |__ classes
                    |__ src

我必须将所有文件从 target/classes 目录复制到目标目录“POM”,并期望目录结构如下

 POM
    |-- submodule
    |         |__ target
    |               |__classes
    |
    |-- subdirectory
              |_target
                    |__ classes

尝试使用以下命令

for dest in POM/; do cp -r modules/*/target/classes $dest; done

但它只复制了 submodule2 目录。

注意:我们只能使用 rsync 命令。

【问题讨论】:

  • 你也可以rsync。

标签: linux bash shell sh


【解决方案1】:

鉴于此文件树:

 tree /tmp/Module
/tmp/Module
├── submodule1
│   └── target
│       └── classes
│           ├── class_1
│           ├── class_2
│           ├── class_3
│           ├── class_4
│           └── class_5
└── submodule2
    └── target
        └── classes
            ├── class_1
            ├── class_2
            ├── class_3
            ├── class_4
            └── class_5

6 directories, 10 files

只需使用cp -R [source path] [target path](即不需要shell循环也不需要glob):

% cp -vR /tmp/Module /tmp/POM
/tmp/Module -> /tmp/POM
/tmp/Module/submodule2 -> /tmp/POM/submodule2
/tmp/Module/submodule2/target -> /tmp/POM/submodule2/target
/tmp/Module/submodule2/target/classes -> /tmp/POM/submodule2/target/classes
/tmp/Module/submodule2/target/classes/class_4 -> /tmp/POM/submodule2/target/classes/class_4
/tmp/Module/submodule2/target/classes/class_3 -> /tmp/POM/submodule2/target/classes/class_3
/tmp/Module/submodule2/target/classes/class_2 -> /tmp/POM/submodule2/target/classes/class_2
/tmp/Module/submodule2/target/classes/class_5 -> /tmp/POM/submodule2/target/classes/class_5
/tmp/Module/submodule2/target/classes/class_1 -> /tmp/POM/submodule2/target/classes/class_1
/tmp/Module/submodule1 -> /tmp/POM/submodule1
/tmp/Module/submodule1/target -> /tmp/POM/submodule1/target
/tmp/Module/submodule1/target/classes -> /tmp/POM/submodule1/target/classes
/tmp/Module/submodule1/target/classes/class_4 -> /tmp/POM/submodule1/target/classes/class_4
/tmp/Module/submodule1/target/classes/class_3 -> /tmp/POM/submodule1/target/classes/class_3
/tmp/Module/submodule1/target/classes/class_2 -> /tmp/POM/submodule1/target/classes/class_2
/tmp/Module/submodule1/target/classes/class_5 -> /tmp/POM/submodule1/target/classes/class_5
/tmp/Module/submodule1/target/classes/class_1 -> /tmp/POM/submodule1/target/classes/class_1

结果:

% tree /tmp/POM
/tmp/POM
├── submodule1
│   └── target
│       └── classes
│           ├── class_1
│           ├── class_2
│           ├── class_3
│           ├── class_4
│           └── class_5
└── submodule2
    └── target
        └── classes
            ├── class_1
            ├── class_2
            ├── class_3
            ├── class_4
            └── class_5

6 directories, 10 files

如果您确实想要一个 Bash 脚本来执行此操作(例如,如果您想处理其中一些文件),您可以按照以下方式进行操作:

#!/bin/bash

cd /tmp || exit
fc=0; dc=0
for fn in /tmp/Module/**/*; do
    if [ -d "$fn" ]; then
        # react to directories here
        printf "directory %s ->t %s\n" "$fn" "${fn/Module/POM}"
        mkdir -p "${fn/Module/POM}"
        (( dc++ ))
    else
        # everything else returned by **/* here
        printf "file %s -> %s\n" "$fn" "${fn/Module/POM}"
        cp "$fn" "${fn/Module/POM}"
        (( fc++ ))
    fi  
done    
printf "\n%'d directories, %'d files" "$dc" "$fc"

打印:

directory /tmp/Module/submodule1 ->t /tmp/POM/submodule1
directory /tmp/Module/submodule1/target ->t /tmp/POM/submodule1/target
directory /tmp/Module/submodule1/target/classes ->t /tmp/POM/submodule1/target/classes
file /tmp/Module/submodule1/target/classes/class_1 -> /tmp/POM/submodule1/target/classes/class_1
file /tmp/Module/submodule1/target/classes/class_2 -> /tmp/POM/submodule1/target/classes/class_2
file /tmp/Module/submodule1/target/classes/class_3 -> /tmp/POM/submodule1/target/classes/class_3
file /tmp/Module/submodule1/target/classes/class_4 -> /tmp/POM/submodule1/target/classes/class_4
file /tmp/Module/submodule1/target/classes/class_5 -> /tmp/POM/submodule1/target/classes/class_5
directory /tmp/Module/submodule2 ->t /tmp/POM/submodule2
directory /tmp/Module/submodule2/target ->t /tmp/POM/submodule2/target
directory /tmp/Module/submodule2/target/classes ->t /tmp/POM/submodule2/target/classes
file /tmp/Module/submodule2/target/classes/class_1 -> /tmp/POM/submodule2/target/classes/class_1
file /tmp/Module/submodule2/target/classes/class_2 -> /tmp/POM/submodule2/target/classes/class_2
file /tmp/Module/submodule2/target/classes/class_3 -> /tmp/POM/submodule2/target/classes/class_3
file /tmp/Module/submodule2/target/classes/class_4 -> /tmp/POM/submodule2/target/classes/class_4
file /tmp/Module/submodule2/target/classes/class_5 -> /tmp/POM/submodule2/target/classes/class_5

6 directories, 10 files

您也可以只使用rsync基本示例如下:

$ rsync -vr /tmp/Module /tmp/POM
# -r for recursive; all targets created and all files copied.

【讨论】:

  • cp: /tmp/Module/**/*: No such file or directory得到这个错误
  • 不要做cp /tmp/Module/**/*。做cp -R /tmp/Module [tgt _path] 没有全局。 cp 有两种模式,您正在使用带有 glob 的文件模式。阅读man 页面。
【解决方案2】:

您可以使用“install -D”复制文件并创建所有前导目标目录。

例子:

#! /bin/bash

mockup ()
{
  rm -rf Module
  for s in {1,2}; do
    for d in main test target/classes target/src; do
      mkdir -p Module/submodule$s/$d
      touch Module/submodule$s/$d/f{1..3}
    done
  done
}

mockup

find Module \
     -wholename '*/classes/*' \
     -exec bash -c 'install -D "$1" "${1/#Module/POM}"' _ {} \;

find 的选项-wholename 用于查找任何名为classes 的目录中的所有文件。

Bash 的参数扩展用于将“Module”替换为“POM”。

但是参数扩展需要一个变量。模式bash -c '...' _ {} 用于将{} 分配给$1

【讨论】:

    猜你喜欢
    • 2016-08-05
    • 2014-11-22
    • 1970-01-01
    • 2017-08-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多