我有一个具有以下结构的目录:
-- 201893208
└── 8Z12
└── ko_8Z12_Full
└── wp_we_8Z12_FullDAT
└── 8Z12_DATFull
└── P011
└── P011_Full
└── 8Z12_FullDAT
└── P011_DATFull
└── 9FZA
└── kl_wt-we-w_kl9-9FZA_Full
└── ffd-9FZA_FullDAT
└── 8fdZ12232_9FZA_DATFull
-- 903240920
└── P0fsa
└── P0fsa_Full
└── P0fsa_FullDAT
└── P0fsa_DATFull
└── Paaaf
└── we-Paaaf_ww_fl_Full
└── Paaaf_FullDAT
└── Paaaf_DATFull
└── 9FZATYYY
└── 9FZATYYY_Full
└── 9FZATYYY_FullDAT
-- wt0340291
└── OPF1121
└── OPF1121_Full
└── 8Z12_DATFull
└── KLOFJ9
└── lop_KLOFJ9_ffj_Full
└── powt_KLOFJ9_DATFull
└── LP02323
└── wr_we_LP02323_Full
└── wr_we_LP02323_FullDAT
上面列出的每个文件夹中都有数千个文件。然后每个里面还有很多子目录。例如8Z12
不仅包含上面列出的三个文件夹,而且还包含数千个文件。
我仅有的想要复制名称_Full
末尾带有 (完整数据目录不应该被复制)并且包含下面列表中的模式
LP02323
KLOFJ9
Paaaf
9FZA
换句话说,包含上面列表中的字符串的目录和 Full
应以他们的名义(但不是 DAT)复制。
因此,在上面的示例中,仅应复制以下目录(及其所有内容和子目录):
wr_we_LP02323_Full
lop_KLOFJ9_ffj_Full
we-Paaaf_ww_fl_Full
kl_wt-we-w_kl9-9FZA_Full
据我了解,rsync
不支持正则表达式,因此必须find
首先完成此操作(如果我错了,请纠正我)。但是,我怎样才能确保检查所有目录和子目录并复制所有相关文件夹,即使它们深埋在几个子目录中(请注意,上面的示例是一个简化的示例)我的原始文件夹的结构)。
那么有两个问题:
- 我如何向 提供模式列表
find
? - 如何通过管道传输
find
to的结果rsync
?
到目前为止,我只想到这个匹配Full
:
find . -regextype sed -regex ".*/.*[^DAT]Full$"
但是如何将 ID 列表添加到该find
命令中呢?
答案1
使用需要出现在目录名称中的字符串文件,shell 循环这些字符串,并且rsync
(假设我们要从变量中的目录复制$source
到变量中的目录$target
):
while IFS= read -r string; do
rsync --archive --exclude='*DAT*/' --include='*/' --include="*$string*_Full/***" --exclude='*' \
--prune-empty-dirs "$source"/ "$target"
done <strings.txt
选项的作用rsync
(任何排除/包含模式的第一次点击都很重要):
--archive
:复制所有权、权限、时间戳等。--exclude='*DAT*/'
DAT
:排除名称中带有 的任何目录。--include='*/'
:考虑所有目录(除了先前模式排除的目录)。这是rsync
到达您感兴趣的实际目录所必需的。--include="*$string*_Full/***"
:考虑与给定模式匹配的所有目录和该目录下的所有内容。如果$string
是的话parrot
,就这样了--include="*parrot*_Full/***"
。--exclude='*'
:不要考虑任何尚未明确包含的内容。--prune-empty-dirs
:不要传输没有明确包含任何内容的目录。
如果您想了解rsync
运行时如何评估模式,请添加-vv
到rsync
命令行。
测试:
$ tree
.
|-- from
| `-- a
| `-- b
| |-- c_A_DATFull
| | `-- file
| |-- c_A_DAT_Full
| | `-- file
| |-- c_A_Full
| | `-- file
| |-- c_B_DATFull
| | `-- file
| |-- c_B_DAT_Full
| | `-- file
| |-- c_B_Full
| | `-- file
| |-- c_C_DATFull
| | `-- file
| |-- c_C_DAT_Full
| | `-- file
| `-- c_C_Full
| `-- file
`-- strings.txt
12 directories, 10 files
$ cat strings.txt
A
B
$ source=from
$ target=to
(在这里运行循环)
$ tree
.
|-- from
[...]
`-- to
`-- a
`-- b
|-- c_A_Full
| `-- file
`-- c_B_Full
`-- file
17 directories, 12 files
通过一次调用rsync
:
set -- --exclude='*DAT*/' --include='*/'
while IFS= read -r string; do
set -- "$@" --include="*$string*_Full/***"
done <strings.txt
set -- "$@" --exclude='*'
rsync --archive "$@" --prune-empty-dirs "$source"/ "$target"
一个find
办法:
set --
while IFS= read -r string; do
set -- "$@" -o -name "*$string*_Full"
done <strings.txt
shift
# "$@" would now be something like
# -name *LP02323*_Full -o -name *Paaaf*_Full -o -name ...etc
find "$source" -type d '(' "$@" ')' ! -name '*DAT*' -exec sh -c '
source=$1; target=$2; shift 2
for pathname do
mkdir -p "$target/${pathname#$source}"
rsync --archive "$pathname"/ "$target/${pathname#$source}"
done' sh "$source" "$target" {} +
这将用于find
生成您要复制的子目录的列表。这些被赋予一个循环它们的小内联脚本。
在循环的每次迭代中,都会创建目标上的相应目录(假设本地副本),并使用rsync
.
从来没有find
用过管道某些其他命令的路径名,除非您可以安排安全地分隔路径名。
有关的: