我有一个名为的文件夹p/
,其中p/
有多个子文件夹,如下所示:
$[~/p] ls
a/ b/ c/
文件夹a/
、b/
和c/
也各有多个子文件夹。我试图在 的每个文件夹和子文件夹中找到与特定模式匹配的文件,p/
并将它们移动到新目录中的相应a/
、b/
和c/
文件夹。因此,a/
会有一个名为 的新子文件夹x/
,x/
并将移动到 中找到的所有匹配文件a/
,b/
会有一个名为 的新子文件夹,并将移动x/
到x/
中找到的所有匹配文件,b/
依此类推。
我努力了:
pth=path/to/p
for dir in ${pth}/*; do
mkdir -- "$dir/x";
find . -name '*match*' -exec mv -t ./x '{}' +;
done
但是它不起作用,它将x/
子文件夹变成了a/
,b/
但是c/
它没有移动任何东西。
我有:
mv: failed to access to './x': No such file or directory
我做错了什么?
答案1
我建议分阶段进行,首先创建目录。接下来,查找并组织搜索结果。由于您的目标在搜索范围内,因此您必须修剪目标,否则可能会导致竞争条件。现在,我们可以一次处理一个项目,但由于这会消耗大量资源,因此在移动搜索之前组织搜索通常更好,因为mv
只接受一个目标会限制我们可以同时移动的文件数量。在这种情况下,我们可以使用关联数组来组织搜索,其中键成为目标。文件将被分配为字符串。重要的是引用文件名中的任何特殊字符,否则,例如,空格将被解释为单词拆分(或以其他方式中断)。
#!/bin/bash
builtin cd p
printf %s/x\\0 {a,b,c} | xargs -0 mkdir -p
declare -A a=()
while IFS=/ read -rd '' b c; do
a[${b@Q}/x]+=\ "${b@Q}/${c@Q}"
done < <(find -type d -path './*/x' -prune -false -o -type f -name '*.txt' -printf %P\\0)
for k in "${!a[@]}"; do
eval printf '%s\\0' "$k" "${a[$k]}" | xargs -0 mv --backup=t -t
done