Prawidłowe rozszerzenia plików


15

Mam około 12000 obrazów różnych typów plików, ale każdy z nich został przemianowany na * .jpg.

Teraz chcę przywrócić im odpowiednie rozszerzenia, jak mogę to zrobić


2
rekurencyjnie, czy w „płaskim” katalogu?
— Jacob Vlijm


1
@steeldriver dość blisko, ale te pliki nie mają rozszerzenia, tutaj mają nieprawidłowe rozszerzenie.
— Jacob Vlijm

1
@JacobVlijm, dlatego nie zgłosiłem pytania jako duplikatu: jednak metody zaproponowane w odpowiedziach mają tutaj wartość, IMHO
— steeldriver

@steeldriver Całkowicie się zgadzam.
— Jacob Vlijm

Odpowiedzi:


22

Możesz to zrobić stosunkowo łatwo w bash:

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

Jest to ten sam pomysł, co odpowiedź @ AB, ale zamiast tego używa się globów powłoki find. Jest ${f%%.*}to nazwa pliku bez rozszerzenia. -0Z filepoleceniem czyni go wydrukować \0po nazwie pliku, który używamy do greptypu pliku. Powinno to działać z dowolnymi nazwami plików, w tym zawierającymi spacje, znaki nowej linii lub cokolwiek innego. ${type,,}To podstęp, aby uzyskać niższe rozszerzenia przypadków. Przekształciłby PNGsię w png.

Nie powiedziałeś w swoim pytaniu, ale jeśli potrzebujesz tego, aby być rekurencyjnym i zejść do podkatalogów, możesz użyć tego w zamian:

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 globstarPozwoli opcję globstar bash, który pozwala **podkatalogi meczu:

globstar

Jeśli jest ustawiony, wzorzec ** użyty w kontekście rozszerzenia nazwy ścieżki będzie pasował do wszystkich plików i zero lub więcej katalogów i podkatalogów. Jeśli po wzorcu występuje znak /, tylko katalogi i podkatalogi są zgodne.


@AB zobacz aktualizację. Pozwala to **na ponowne przechodzenie do podkatalogów.
— terdon

Te średniki na końcu każdej linii są zbędne, prawda?
— Paddy Landau

@PaddyLandau tak, testowałem to jako linijkę i dodałem tutaj nowe linie dla przejrzystości. Zapomniałem je usunąć. Pamiętaj, że nie są w błędzie, są po prostu zbędne, jak mówisz.
— terdon

Świetnie, choć filenie zawsze wydaje się, jakie rozszerzenie wydaje się: na przykład zmienia tutaj plik bash foo.bourne-again!
— Campa,

1
@Campa nie, oczywiście że nie. Dodałby także fałszywe rozszerzenia do plików binarnych, normalnych plików tekstowych, skryptów perl i python, a lista jest długa. Pytanie dotyczyło konkretnie obrazów, które zazwyczaj mają takie same nazwy jak ich zwykłe rozszerzenia. Pamiętaj, że rozszerzenia w systemie Linux są opcjonalne, z nielicznymi wyjątkami, w rzeczywistości nic nie robią. Pomagają użytkownikowi uporządkować dane, system operacyjny nie dba o nie.
— terdon

11

Poniższego skryptu można użyć do (rekurencyjnej) zmiany nazwy nieprawidłowo ustawionego rozszerzenia .jpgna prawidłowe. W przypadku znalezienia nieczytelnego pliku zgłosi go w danych wyjściowych skryptu.

Skrypt użyć imghdrmodułu rozpoznawania następujących typów: rgb, gif, pbm, pgm, ppm, tiff, rast, xbm, jpeg, bmp, png. Więcej o imghdrmodule tutaj . Lista może zostać rozszerzona o więcej typów, jak wspomniano w linku.

W tej chwili zmienia nazwy plików z rozszerzeniem .jpg, jak wspomniano w pytaniu. Po niewielkiej zmianie można zmienić nazwę dowolnego rozszerzenia lub określonego zestawu rozszerzeń na prawidłowe (lub bez rozszerzenia, jak tutaj ).

Scenariusz:

#!/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)

Jak używać

  1. Skopiuj skrypt do pustego pliku i zapisz go jako rename.py
  2. Uruchom go za pomocą polecenia:

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

+1 za proste i łatwe do odczytania, w przeciwieństwie do rozwiązań opartych na bash.
— Davide

3

Uwaga: moje podejście wydaje się zbyt skomplikowane. Wolałbym, żeby terdons odpowiedział na twoim miejscu.


Możesz użyć polecenia, fileaby określić typ pliku:

% 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

Dzięki tym informacjom można zmienić nazwę plików:

Wykonaj test, zanim zastosujesz polecenie do swoich zdjęć

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)
   }'

Przykład

% 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

Pamiętaj, że spowoduje to uszkodzenie w mało prawdopodobnym przypadku, gdy dowolna nazwa pliku zawiera znaki nowej linii.
— terdon

@terdon Tak, myślałem. Niestety nie mam pojęcia, co mogę zrobić. Możesz pomóc?
— AB

Nie mam pojęcia, jak to zrobić poprawnie za pomocą awk. To nie jest odpowiednie narzędzie do pracy. Użyj albo find -exec bash -c "..."zrób wszystko, co tam jest, albo użyj, while read -d '' name typeaby podzielić nazwę pliku i filedane wyjściowe, a następnie parsuj, $typeaby uzyskać typ pliku. Naprawdę nie warto, zobacz moją odpowiedź, jak to zrobić o wiele łatwiej w czystym (ish) bashu.
— terdon
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.