根据与单独文件内容匹配的当前文件名更改文件名

根据与单独文件内容匹配的当前文件名更改文件名

在一个目录中,我有几个 PNG 和一个文本文件。 PNG 以 UPC 条形码命名,如052100029962.png052100045535.png等,我有一个文本文件upcs.txt,其中每一行包含与产品名称合并的 UPC 代码,如下所示:

...
052100029962mccormickpepper
052100045535mccormickonesheet
...

我想将每个*.png*文件重命名为它的产品名称,不带 UPC 编号,使用与文本文件中的字符串匹配的当前文件名 — 所以052100029962.png我不会使用mccormickkeeper.png.这出人意料地困难。我尝试过以下各种方法但没有成功。

for f in $(find . -iname "*.png"); do
    while read -r line; do
        if [[ "$f" == *"$line"* ]]; then  ## also tried =~
            cp "$f" "$line";
        fi
    done < upcs.txt
done

我所说的“品种”是指切换操作顺序,例如,将循环放在循环while之前for,甚至创建另一个仅包含产品名称的文本文件,以便我read也可以对它们进行比较。对于后者,我做了:

for f in $(find . -iname "*.png"); do
    while read -r line; do
        if [[ "$f" == *"$line"* ]]; do
            while read -r line2; do
                cp "$f" "$line2";
            done < upcs_names_only.txt;
        fi;
    done < upcs.txt;
done

while我什至尝试在调用循环之前放置第二个循环if

最后,我知道即使公式正确,上述循环也会不是保留.png扩展名。为了解决这个问题,我准备手动选择结果并添加.png.

我究竟做错了什么?谁能帮助我更好地理解逻辑?

答案1

对于每行包含两个字段的文件,您必须使用分隔符。这里 ased插入这个分隔符,结果逐行给出mv

#!/bin/bash
while read -r oldname newname; do
    [ -f "${oldname}.png" ] && echo mv -- "${oldname}.png" "${newname}.png"
done < <(sed 's/^[0-9]*/& /' upcs.txt)

echo测试后移除。当然,我假设您的第一个字段始终是数字序列,第二个字段没有空格,不以数字开头等。

如果您需要任何其他操作,例如检查重复的目标名称,您可以首先在文件上执行此操作。或者,如果您需要在任何情况下mv都不覆盖现有目标,请使用-n( --no-clobber),同样-i( --interactive) 也会出于同样的原因提示用户输入。

答案2

在您的脚本中, $f var 将是 052100029962.png ,它与 upcs.txt 中的任何行都不匹配:

052100029962.png doesn't match *052100029962mccormickpepper*

假设 UPC 编号始终为 12 个字符长或者产品名称不以数字开头,我将迭代文本文件行,使用正则表达式分割行,搜索文件名 {$upc}.png 和将其重命名为 {$product_name}.png。

#!/bin/bash
while read -r line; do
    if [[ $line =~ ([0-9]{12})(.*) ]]; then
        upc="${BASH_REMATCH[1]}.png"
        name="${BASH_REMATCH[2]}.png"
        if [[ -f $upc ]]; then
            if [[ ! -f $name ]]; then
                cp "$upc" "$name"
            else
                echo "$name already exists"
            fi
        fi
    fi
done < upcs.txt

答案3

一种方法如下。但请注意,这仅查看当前目录中的文件,并且不会递归到子目录中。

while IFS= read -r l <&3
do
  barcode=${l%%[!0-9]*}
  value=${l#"$barcode"}
  [ -f "$barcode.png" ] && \
  printf '%s.png ' "$barcode" "$value" 
done 3< upcs.txt | xargs -rn 2 -t cp -pdf --

相关内容