먼저 백업을 하세요.

먼저 백업을 하세요.

내 디렉토리에는 확장자 없이 약 100,000개의 파일이 있습니다. 파일이 무엇인지 모르겠습니다. 일부는 pdf, jpg, png, xls 등인 것 같습니다.

각 파일에 확장자를 추가하는 쉬운 방법이 있습니까?

내 현재 아이디어는 각 파일에 대한 명령을 생성하는 스크립트를 만들고 fileif(예: grep png)와 함께 grep을 사용하여 결과를 얻은 다음 true이면 png를 추가하는 것입니다.

누구든지 더 좋은 방법이 있다면.

인사

답변1

쉬운 일이 아닙니다. 옵션이 file(1)있지만 --extension내 테스트(Debian/bullseye)에서는 대부분의 파일에 물음표( ???)가 표시됩니다.

그리고 알려진 모든 파일 유형에 대한 인코딩은 최소 3000개 이상의 파일 유형이 감지된 것으로 보이기 case..esac때문에 작동하지 않을 가능성이 높습니다 .file

❯ file -l | wc -l
3186

먼저, 특정 디렉터리에서 파일 형식 목록을 얻으려고 합니다.

노트,zsh 와일드카드여기에 사용됨:

❯ file -p -n -b .*(.) *(.) | sort | uniq
ASCII text
ASCII text, with no line terminators
ASCII text, with very long lines
ASCII text, with very long lines, with no line terminators
data
empty
JPEG image data, JFIF standard 1.01, resolution (DPI), density 300x300, segment length 16, Exif Standard: [TIFF image data, big-endian, direntries=0], baseline, precision 8, 96x96, components 3
JSON data
Non-ISO extended-ASCII text, with very long lines, with CRLF, LF line terminators, with escape sequences
Python script, UTF-8 Unicode text executable
UTF-8 Unicode text
UTF-8 Unicode text, with very long lines
very short file (no magic)
X11 Xauthority data

다음 find줄은 동일한 출력을 생성합니다.

find -maxdepth 1 -type f -exec file -p -n -b {} \; | sort | uniq

이 목록에서 파일 형식 확장자 맵/찾기 파일을 만들고 이를 사용하여 파일 이름을 바꿉니다.

ext1;ASCII text
ext2;ASCII text, with no line terminators
ext3;ASCII text, with very long lines
ext4;ASCII text, with very long lines, with no line terminators
ext5;data
ext6;empty
ext7;JPEG image data, JFIF standard 1.01, resolution (DPI), density 300x300, segment length 16, Exif Standard: [TIFF image data, big-endian, direntries=0], baseline, precision 8, 96x96, components 3
ext8;JSON data
ext9;Non-ISO extended-ASCII text, with very long lines, with CRLF, LF line terminators, with escape sequences
ext10;Python script, UTF-8 Unicode text executable
ext11;UTF-8 Unicode text
ext12;UTF-8 Unicode text, with very long lines
ext13;very short file (no magic)
ext14;X11 Xauthority data

화타이

답변2

perl기반 renameFile::MimeInfo::MagicPerl 모듈 사용 ( libfile-mimeinfo-perlDebian 기반 시스템의 패키지, 일반적으로 종속성이므로 데스크톱 설치에 기본적으로 설치됨(권장) xdg-utils):

rename -n -- '
  use File::MimeInfo::Magic qw(mimetype extensions);
  my $ext; $_ .= ".$ext" if ! /\./ && ($ext = extensions mimetype$_)' *

( -n올바르게 보이면 연습 실행을 제거합니다).

답변3

이 답변에서는 하나의 디렉터리에 비교적 깨끗한 파일 이름 목록이 있고 파일 이름에 공백, 탭, 줄 바꿈 및 기타 바람직하지 않은 문자가 포함되어 있지 않다고 가정합니다. 여기의 코드 조각은 bash셸용입니다.

먼저 백업을 하세요.

수천 개의 파일 이름을 자동으로 변경할 때마다 항상 문제가 발생할 가능성이 있습니다. 하나의 문제에 십만 개의 파일을 곱하면 다시 시도하기 전에 해결해야 할 십만 개의 문제가 됩니다.

먼저 백업을 만드세요:

$ mkdir ~/my-backup
$ rsync -av ./ ~/my-backup/

이제 문제가 발생하면 백업에서 복원할 수 있습니다.

$ rsync -av --delete ~/my-backup/ ./

file극적인 변화

이 명령 구현의 품질은 file배포판에 따라 다릅니다. 확실히, 사용되는 magic파일이 file최신일 수 있으므로 버전이 최신일수록 좋습니다. 가능하다면 rsync더 나은 버전의 file.

그렇다면 내 시스템의 구현은 어떻게 작동합니까 file?

우리가 제공하는 와일드카드 glob에서 작동할 함수를 정의해 보겠습니다 fext. 또한 file -b --extension원하는 대로 출력을 정규화하기 위해 몇 가지 간단한 변환을 통해 출력을 실행합니다 .filesedfile

fext () {
  file -b --extension "$@" |
  sed -e 's-^jpeg/jpg/jpe/jfif$-jpg-' |
  sed -e 's-^pdf$-PDF-' |
  cat
}

쓸모가 없었다면 죄송합니다 cat. 모듈성을 위해 포함되었으므로 파일 형식이 여러 확장자 ​​문자열을 반환하는 경우 해당 sed줄을 복사하고 붙여넣고 편집하여 해당 배수를 원하는 단일 확장자 또는 원하는 대문자 등으로 변환할 수 있습니다. 이 예에서 fileas로 식별된 파일은 jpeg/jpg/jpe/jfif확장자를 가지며 jpg, as로 식별된 파일은 pdf확장자를 갖습니다 PDF. 이는 cat변환 목록 끝에 있는 아무 작업도 하지 않는 자리 표시자일 뿐입니다.

확장자가 여러 개인 다른 파일 형식은 어떻습니까?

file여러 확장자를 반환하는 컬렉션에서 가능한 모든 파일 형식을 열거했는지 확인하는 것이 중요합니다. 테스트하기 쉽습니다.

$ fext * | grep /

출력이 없어야 합니다. 출력이 있는 경우 정의 sed에 다른 줄을 추가 해야 합니다 fext.

이제 fext전체 파일 컬렉션에 대해 실행하여 인식할 수 있다고 생각하는 파일 수와 인식하지 못하는 파일 수를 확인할 수 있습니다.

나는 약하게 선택된 152개의 파일로 구성된 테스트 그룹을 사용하고 있습니다. 저는 세 가지 시스템에서 실행 중입니다.

$ fext * | sort | uniq -c

우분투 18.04.2 LTS:

$ fext * | sort | uniq -c
    137 ???
     15 jpg

FreeBSD 13.1:

$ fext * | sort | uniq -c
  28 ???
  76 PDF
  15 jpg
  32 png
   1 tif,tiff

우분투 22.04 LTS:

$ fext * | sort | uniq -c
     28 ???
     15 jpg
     76 PDF
     32 png
      1 tif,tiff

magic이 유틸리티에서 사용하는 파일에서 버그를 발견했습니다 file. 다행히도 이 문제는 우리 함수에서 쉽게 해결할 수 있습니다 fext.

$ fext () {
  file -b --extension "$@" |
  sed -e 's-^jpeg/jpg/jpe/jfif$-jpg-' |
  sed -e 's-^pdf$-PDF-' |
  sed -e 's-^tif,tiff$-tiff-' |
  cat
}
$ fext * | sort | uniq -c
     28 ???
     15 jpg
     76 PDF
     32 png
      1 tiff

훌륭한. 여기서 중요한 점은 슬래시(또는 쉼표!)가 없다는 것입니다. 우리 는 file. 인식할 수 없는 유형의 파일에 기본 확장자를 할당 file하도록 기능을 더욱 구체화할 수 있습니다 .fextfile

$ fext () {
  file -b --extension "$@" |
  sed -e 's-^jpeg/jpg/jpe/jfif$-jpg-' |
  sed -e 's-^pdf$-PDF-' |
  sed -e 's-^tif,tiff$-tiff-' |
  sed -e 's-^???$-unknown-' |
  cat
}
$ fext * | sort | uniq -c
     15 jpg
     76 PDF
     32 png
      1 tiff
     28 unknown

원하는 경우 인식되지 않은 파일 grep의 특정 파일 이름을 나열하고 볼 수 있습니다.file

$ for f in *; do [ -f "$f" ] && printf '%10s %s\n' "$(fext "$f")" "$f"; done | grep -w unknown 

내 (약한) 샘플 세트에서 "알 수 없는" 파일은 주로 PostScript 파일입니다. file이를 인식하지만 magic파일은 PostScript 파일의 확장자를 지정하지 않습니다.

따라서 fext모든 파일에 확장자를 제공하면 인식할 수 없는 파일에는 file확장자가 unknown.

$ for f in *; do [ -f "$f" ] && mv -vi "$f" "$f.$(fext "$f")"; done

답변4

불행하게도 이것은 알려진 확장자를 가진 많은 형식을 file -b --extension반환하므로 별로 도움이 되지 않습니다 . ???대신, 예상치 못한 일이 발생할 경우를 대비해 관심 있는 디렉터리를 먼저 복제하세요.

# using hard links
cp --link /path/to/originals /path/to/files

# using reflinks on supported file systems
cp --reflink=auto /path/to/originals /path/to/files

그런 다음 디렉터리에 MIME 유형 목록을 만듭니다.

find /path/to/files -type f -exec file -b --mime-type {} \; | sort -u

출력은 다음과 같습니다.

application/epub+zip
application/msword
application/pdf
application/zip
image/gif
image/jpeg
image/png
image/svg+xml
text/html
text/plain
text/rtf
text/xml

이제 MIME 유형에 따라 적절한 확장자로 파일 이름을 바꾸는 bash스크립트를 만듭니다(필요한 경우).add_ext.sh

#!/usr/bin/env bash

[ $# -lt 1 ] && echo "Usage: $0 <FILE>" && exit 1

mimetype=$(file -b --mime-type "$1")
extension="${1#**.}"
new_ext="unset"

case $mimetype in
   'application/epub+zip')
      new_ext="epub"
      ;;

   'application/msword')
      new_ext="doc"
      ;;

   'application/pdf')
      new_ext="pdf"
      ;;

   'application/zip')
      new_ext="zip"
      ;;

   'image/gif')
      new_ext="gif"
      ;;

   'image/jpeg')
      new_ext="jpeg"
      ;;

   'image/png')
      new_ext="png"
      ;;

   'image/svg+xml')
      new_ext="svg"
      ;;

   'text/html')
      new_ext="html"
      ;;

   'text/plain')
      new_ext="txt"
      ;;

   'text/rtf')
      new_ext="rtf"
      ;;

   'text/xml')
      new_ext="xml"
      ;;
esac

[ "$new_ext" != "unset" ] \
   && [ "$extension" != "$new_ext" ] \
   && [ ! -e "$1.$new_ext" ] \
   && mv "$1" "$1.$new_ext"

chmod +x add_ext.shfind파일을 사용하여 스크립트를 실행하기 전에 잊지 마십시오.

find /path/to/files -type f -exec ./add_ext.sh {} \;

관련 정보