별도 파일의 내용과 일치하는 현재 파일 이름을 기반으로 파일 이름을 변경합니다.

별도 파일의 내용과 일치하는 현재 파일 이름을 기반으로 파일 이름을 변경합니다.

디렉토리에는 여러 개의 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루프를 호출하기 전에 두 번째 루프를 배치해 보기도 했습니다 if.

마지막으로, 공식이 정확하더라도 위의 루프는아니요.png확장자를 유지하세요 . 이 문제를 해결하기 위해 수동으로 결과를 선택하고 .png.

내가 뭘 잘못했나요? 누구든지 논리를 더 잘 이해하도록 도와줄 수 있나요?

답변1

한 줄에 두 개의 필드가 있는 파일의 경우 구분 기호를 사용해야 합니다. 여기에 sed이 ​​구분 기호를 삽입하면 결과가 한 줄씩 제공됩니다.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 --

관련 정보