別のファイルの内容に一致する現在のファイル名に基づいてファイル名を変更します。

別のファイルの内容に一致する現在のファイル名に基づいてファイル名を変更します。

ディレクトリには複数のPNGとテキストファイルがあります。 PNG名は、などのUPCバーコードにちなんで指定されます。052100029962.png各行には、次のように製品名とマージされたUPCコードを含む052100045535.pngテキストファイルがあります。upcs.txt

...
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ループを呼び出す前に、2番目のループを配置してみましたif

最後に、公式が正確であっても、上記のループはいいえ.png拡張子を維持してください。この問題を解決するには、手動で結果を選択します.png

私は何が間違っていましたか?誰でもロジックをよりよく理解するのに役立ちますか?

答え1

1行に2つのフィールドがあるファイルの場合は、区切り文字を使用する必要があります。ここにsedこの区切り記号を挿入すると、結果が1行ずつ提供されます。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テスト後に削除してください。もちろん、最初のフィールドは常に一連の数字であり、2番目のフィールドにはスペースがなく、数字で始まらないとします。

重複先の名前解決などの追加操作が必要な場合は、まずファイルでこれを実行できます。または、いずれの場合でも既存の宛先を上書きしたくない場合()を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

これを行う1つの方法は次のとおりです。ただし、これは現在のディレクトリのファイルだけを見て、サブディレクトリに再帰的に移動しないことに注意してください。

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 --

関連情報