使用嵌套通配符复制和重命名

使用嵌套通配符复制和重命名

我有以下文件结构:

raw:
    F1:
        file1.pdf
    F2:
        file2.pdf
    (...)
pdf:
    (...)

每个文件夹始终只有一个 pdf 文件,并且文件/文件夹名称可以是任意的。

我想将raw目录中的所有pdf文件复制到pdf目录中,并将其文件名替换为其根文件夹名称。对于上面的例子,结果如下:

raw:
    F1:
        file1.pdf
    F2:
        file2.pdf
    (...)
pdf:
    F1.pdf
    F2.pdf
    (...)

我已经阅读过有关通配符复制的内容,但这显然是一个问题,因为我必须使用两个嵌套的通配符来复制我的文件。所以这显然行不通:

cp raw/*/*.pdf pdf/*.pdf

有没有办法解决这个问题,或者我是否必须循环我的文件夹并使用正则表达式来分割路径?

答案1

您可以使用通配符进行复制,这样就可以了。但是,您需要重命名文件,而不仅仅是复制它们,这意味着您必须为每个文件分配一个新名称,这意味着循环是不可避免的。您最多可以使用一个为您执行循环的工具。

如果您有perl-renamerenamed在基于 Debian 的系统上调用),您可以执行以下操作:

$ rename -n 's|raw/([^/]+)/.*pdf|pdf/$1.pdf|' raw/*/*.pdf
raw/F1/file1.pdf -> pdf/F1.pdf
raw/F2/file2.pdf -> pdf/F2.pdf

.pdf这将找到的任何一级子目录中以 结尾的所有文件名raw,将它们重命名为其父文件夹的名称加上.pdf扩展名,并将它们保存在pdf/.这-n意味着“只打印您将要执行的操作,而不是执行此操作”,因此,如果您对此感到满意,请运行该命令,而无需-n实际重命名文件:

rename 's|raw/([^/]+)/.*pdf|pdf/$1.pdf|' raw/*/*.pdf

或者,您可以使用 shell 循环:

for f in raw/*/*pdf; do 
    new=$(sed -E 's|raw/([^/]+)/.*|pdf/\1.pdf|' <<<"$f"); 
    echo "mv -- $f $new"; 
done
mv raw/F1/file1.pdf pdf/F1.pdf
mv raw/F2/file2.pdf pdf/F2.pdf

同样,如果您对它的工作感到满意,请删除回显以实际重命名文件:

for f in raw/*/*pdf; do 
    new=$(sed -E 's|raw/([^/]+)/.*|pdf/\1.pdf|' <<<"$f"); 
    mv -- "$f" "$new"; 
done

重要的:两种解决方案都假设每个目录只有一个文件,因此不会发生冲突。他们将删除您拥有的任何额外文件,因为同一子目录中的所有文件将获得相同的名称。

您可以尝试使用-i每个相应工具的选项(mvan rename),这将使它们在覆盖同名文件之前要求您确认。这将使解决方案:

rename -i 's|raw/([^/]+)/.*pdf|pdf/$1.pdf|' raw/*/*.pdf

for f in raw/*/*pdf; do 
    new=$(sed -E 's|raw/([^/]+)/.*|pdf/\1.pdf|' <<<"$f"); 
    mv -i -- "$f" "$new"; 
done

答案2

使用嵌套循环:

shopt -s nullglob  # To prevent failures if there's no pdf in a dir.
for dir in raw/* ; do
    for pdf in "$dir"/*.pdf ; do
        cp -- "$pdf" pdf/"${dir#raw/}".pdf  # Remove the "raw/" part
    done
done

或迭代文件并应用参数扩展两次以生成目标名称:

for pdf in raw/*/*.pdf ; do
    target=${pdf#raw/}  # Remove the "raw/" part
    target=${target%/*}  # Remove the filename
    cp -- "$pdf" pdf/"$target".pdf
done

答案3

zsh

autoload -Uz zmv # best in ~/.zshrc
zmv -C 'raw/(*)/*.pdf' 'pdf/$1.pdf'

相关内容