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

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

ディレクトリには複数の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

おすすめ記事