У меня есть папка с именем p /, а в p / у меня есть несколько подпапок, например:
$[~/p] ls
a/ b/ c/
a / b / и c / также имеют несколько вложенных папок каждая. Я пытаюсь найти файл, соответствующий определенному шаблону, в каждой папке и подпапке p / и переместить их в новый каталог в соответствующие папки a /, b / и c /. { {1}} Итак, 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: не удалось получить доступ к './x': нет такого файла или каталога
Что я делаю не так ?? Не могли бы вы мне помочь?
Я предлагаю делать это поэтапно, сначала создавая каталоги. Затем найдите и систематизируйте результат поиска. Поскольку ваша цель находится внутри поиска, вы должны обрезать цель, иначе это может привести к условиям гонки. Теперь мы можем обрабатывать один элемент за раз, но, поскольку он потребляет много ресурсов, обычно лучше организовать поиск, прежде чем перемещать их, поскольку 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