올바른 파일 확장자


15

파일 형식이 다른 약 12000 개의 이미지가 있지만 그 중 하나의 이름은 * .jpg로 바뀌 었습니다.

이제 적절한 확장 기능을 다시 제공하고 싶습니다. 어떻게해야합니까


2
재귀 적으로 또는 "평평한"디렉토리?
Jacob Vlijm 2016 년


1
@steeldriver는 매우 가깝지만 해당 파일 의 확장자 는 없습니다 . 여기에서 확장자 가 잘못되었습니다 .
Jacob Vlijm 2016 년

1
@JacobVlijm 이것이 바로 질문을 중복으로 표시하지 않은 이유입니다. 그러나 답변 에서 제안 된 방법은 여기에 가치가 있습니다. IMHO
steeldriver

@steeldriver 나는 완전히 동의한다.
Jacob Vlijm 2016 년

답변:


22

bash에서 비교적 쉽게 할 수 있습니다.

for f in *jpg; do 
    type=$(file -0 -F" " "$f" | grep -aPo '\0\s*\K\S+') 
    mv "$f" "${f%%.*}.${type,,}"  
done

이것은 @AB의 답변과 동일하지만 셸 대신 쉘 글롭을 사용 find합니다. 는 ${f%%.*}확장자가없는 파일 이름입니다. -0file명령은이 인쇄하게 \0우리가 다음에 사용하는 파일 이름 뒤에 grep파일 형식. 공백, 줄 바꿈 또는 다른 것을 포함하는 파일을 포함하여 임의의 파일 이름으로 작동해야합니다. 이것은 ${type,,}소문자 확장을 얻는 트릭입니다. 로 변환 PNG됩니다 png.

귀하의 질문에 대답하지 않았지만 이것이 재귀 적이어야하고 하위 디렉토리로 내려 가려면 다음을 대신 사용할 수 있습니다.

shopt -s globstar
for f in **/*jpg; do 
    type=$(file -0 -F" " "$f" | grep -aPo '\0\s*\K\S+') 
    mv "$f" "${f%%.*}.${type,,}"  
done

shopt -s globstar할 수 배쉬의 globstar 옵션을 가능하게 **일치하는 하위 디렉토리 :

글로브 스타

설정된 경우 경로 확장 컨텍스트에서 사용되는 패턴 **은 모든 파일과 0 개 이상의 디렉토리 및 하위 디렉토리와 일치합니다. 패턴 뒤에 /가 오면 디렉토리와 서브 디렉토리 만 일치합니다.


@AB는 업데이트를 참조하십시오. **하위 디렉토리로 재귀를 허용 합니다.
terdon

각 줄의 끝에있는 세미콜론은 중복되지 않습니까?
Paddy Landau

@PaddyLandau 네, 하나의 라이너로 테스트하고 명확성을 위해 개행을 추가했습니다. 나는 그것들을 제거하는 것을 잊었다. 당신이 말한대로 중복되지는 않습니다.
terdon

file확장명을 항상 지정하지는 않지만 훌륭 foo.bourne-again합니다. 예를 들어 bash 파일을 여기로 바꿉니다!
Campa

1
@Campa 아니오, 물론 아닙니다. 또한 바이너리 파일, 일반 텍스트 파일, perl 및 python 스크립트에 가짜 확장을 추가하고 목록을 계속 진행합니다. 질문은 이미지 에 대해 구체적 으로 묻고 있으며 일반적인 확장명과 이름이 같은 경향이 있습니다. Linux의 확장은 선택 사항이며, 예외는 거의 없지만 실제로는 아무것도하지 않습니다. 그들은 사용자가 데이터를 구성하는 것을 돕고 OS는 데이터를 신경 쓰지 않습니다.
terdon

11

아래 스크립트를 사용하면 잘못 설정된 확장명 .jpg을 올바른 이름으로 (재귀 적으로) 바꿀 수 있습니다 . 읽을 수없는 파일을 찾으면 스크립트 출력에보고합니다.

스크립트는 사용하는 imghdr다음과 같은 유형을 인식, 모듈 : rgb, gif, pbm, pgm, ppm, tiff, rast, xbm, jpeg, bmp, png. imghdr모듈 에 대한 자세한 내용은 여기를 참조하십시오 . 링크에 언급 된대로 목록을 더 많은 유형으로 확장 할 수 있습니다.

그대로 .jpg질문에서 언급했듯이 확장명을 가진 파일의 이름을 구체적으로 바꿉니다 . 약간만 변경하면 확장명 또는 특정 확장명을 올바른 확장명으로 바꾸거나 확장명이없는 ( 여기 와 같이 ) 이름을 바꿀 수 있습니다 .

스크립트 :

#!/usr/bin/env python3
import os
import imghdr
import shutil
import sys

directory = sys.argv[1]

for root, dirs, files in os.walk(directory):
    for name in files:
        file = root+"/"+name
        # find files with the (incorrect) extension to rename
        if name.endswith(".jpg"):
            # find the correct extension
            ftype = imghdr.what(file)
            # rename the file
            if ftype != None:
                shutil.move(file, file.replace("jpg",ftype))
            # in case it can't be determined, mention it in the output
            else:
                print("could not determine: "+file)

사용하는 방법

  1. 스크립트를 빈 파일로 복사하여 다른 이름으로 저장하십시오. rename.py
  2. 다음 명령으로 실행하십시오 :

    python3 /path/to/rename.py <directory>
    

bash 기반 솔루션과 달리 간단하고 읽기 쉬운 +1
Davide

3

참고 : 내 접근 방식이 너무 복잡해 보입니다. 나는 당신의 장소에서 terdons 답변을 선호합니다.


명령 file을 사용 하여 파일 유형을 결정할 수 있습니다 .

% file 20050101_14-24-37_330.jpg 
20050101_14-24-37_330.jpg: JPEG image data, EXIF standard 2.2, baseline, precision 8, 1200x1600, frames 3

% file test.jpg
test.jpg: PNG image data, 1192 x 774, 8-bit/color RGBA, non-interlaced

이 정보를 사용하여 파일 이름을 바꿀 수 있습니다.

이미지에 명령을 적용하기 전에 테스트를 수행하십시오

find . -type f -iname "*.jpg" -print0 | xargs -0 -I{} file -F"<separator>" {} | 
 awk -F " image data" '{print $1}' | 
  awk -F"<separator> " '{
   system("mv \""$1"\" $(dirname \""$1"\")/$(basename -s .jpg \"" $1 "\")."$2)
   }'

% find . -type f -name "*.jpg"
./test.jpg
./sub/20050101_14-24-37_330.jpg

% find . -type f -iname "*.jpg" -print0 | xargs -0 -I{} file -F"<separator>" {} | awk -F " image data" '{print $1}' | awk -F"<separator> " '{system ("mv \""$1"\" $(dirname \""$1"\")/$(basename -s .jpg \"" $1 "\")."$2)}'

% find . -type f -iname "*"    
./test.PNG
./sub/20050101_14-24-37_330.JPEG

파일 이름에 개행 문자가 포함되어있는 경우는 거의 없습니다.
terdon

@terdon 예, 생각하고 있습니다. 불행히도 나는 내가 무엇을 할 수 있는지 전혀 모른다. 도울 수 있니?
AB

awk를 사용하여 올바르게 수행하는 방법을 모르겠습니다. 작업에 적합한 도구는 아닙니다. find -exec bash -c "..."거기에서 모든 것을 사용 하고 수행하거나 while read -d '' name type파일 이름과 file출력 을 분할 한 다음 파싱 $type하여 파일 유형을 얻으십시오. 실제로 가치가 없어, 순수한 배쉬에서 훨씬 쉽게 수행하는 방법에 대한 내 대답을 참조하십시오.
terdon
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.