将名称中带有模式的文件移动到与其名称具有相同模式的文件夹

Moving files with a pattern in their name to a folder with the same pattern as its name

我的目录包含数百个与此类似的文件和目录:

508471/
ae_lstm__ts_ 508471_detected_anomalies.pdf
ae_lstm__508471_prediction_result.pdf
mlp_508471_prediction_result.pdf
mlp__ts_508471_detected_anomalies.pdf
vanilla_lstm_508471_prediction_result.pdf
vanilla_lstm_ts_508471_detected_anomalies.pdf

598690/
ae_lstm__ts_598690_detected_anomalies.pdf
ae_lstm__598690_prediction_result.pdf
mlp_598690_prediction_result.pdf
mlp__ts_598690_detected_anomalies.pdf
vanilla_lstm_598690_prediction_result.pdf
vanilla_lstm_ts_598690_detected_anomalies.pdf

有些文件夹的名称是 ID 号,例如 508471 和 598690。
在与这些文件夹相同的路径中,有 pdf 个文件将此 ID 号作为其名称的一部分。我需要将名称中具有相同 ID 的所有 pdf 文件移动到它们的相关目录中。

我尝试了以下 shell 脚本,但它没有任何作用。我做错了什么?
我正在尝试遍历所有目录,找到名称中包含 id 的文件,并将它们移动到同一目录:

for f in ls -d */; do
    id=${f%?}  # f value is '598690/', I'm removing the last character, `\`, to get only the id part 
    find . -maxdepth 1 -type f -iname *.pdf -exec grep $id {} \; -exec mv -i {} $f \;
done

在 Unix 中请使用下面的命令

find . -name '*508471*' -exec bash -c 'echo mv [=10=] ${0/508471/598690}' {} \;
#!/bin/sh
find . -mindepth 1 -maxdepth 1 -type d -exec sh -c '
    for d in "$@"; do
        id=${d#./}
        for file in *"$id"*.pdf; do
            [ -f "$file" ] && mv -- "$file" "$d"
        done
    done
' findshell {} +

这将查找当前目录中的每个目录(例如,查找 ./598690)。然后,它从相对路径中删除 ./ 并选择包含结果 id (598690) 的每个文件,将其移动到相应的目录。

如果您不确定这会做什么,请在 &&mv 之间放置一个 echo,它将列出脚本将执行的 mv 操作。

记住,do not parse ls

下面的代码应该可以完成所需的工作。

for dir in */; do find . -mindepth 1 -maxdepth 1 -type f -name "*${dir%*/}*.pdf" -exec mv {} ${dir}/ \;; done

其中 */ 将仅考虑给定目录中存在的目录,find 将仅搜索给定目录中与 *${dir%*/}*.pdf 匹配的文件,即包含目录名称的文件名它的子字符串和最后的 mv 会将匹配的文件复制到目录中。

您可以在这些 pdf 文件和目录的父目录中使用此 for 循环:

for d in */; do
    compgen -G "*${d%/}*.pdf" >/dev/null && mv *"${d%/}"*.pdf "$d"
done

compgen -G 用于检查给定的 glob 是否匹配。