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ć
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ć
Odpowiedzi:
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. -0
Z file
poleceniem czyni go wydrukować \0
po nazwie pliku, który używamy do grep
typu 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 PNG
się 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 globstar
Pozwoli 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.
**
na ponowne przechodzenie do podkatalogów.
file
nie zawsze wydaje się, jakie rozszerzenie wydaje się: na przykład zmienia tutaj plik bash foo.bourne-again
!
Poniższego skryptu można użyć do (rekurencyjnej) zmiany nazwy nieprawidłowo ustawionego rozszerzenia .jpg
na prawidłowe. W przypadku znalezienia nieczytelnego pliku zgłosi go w danych wyjściowych skryptu.
Skrypt użyć imghdr
modułu rozpoznawania następujących typów: rgb
, gif
, pbm
, pgm
, ppm
, tiff
, rast
, xbm
, jpeg
, bmp
, png
. Więcej o imghdr
module 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 ).
#!/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)
rename.py
Uruchom go za pomocą polecenia:
python3 /path/to/rename.py <directory>
Uwaga: moje podejście wydaje się zbyt skomplikowane. Wolałbym, żeby terdons odpowiedział na twoim miejscu.
Możesz użyć polecenia, file
aby 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
find -exec bash -c "..."
zrób wszystko, co tam jest, albo użyj, while read -d '' name type
aby podzielić nazwę pliku i file
dane wyjściowe, a następnie parsuj, $type
aby uzyskać typ pliku. Naprawdę nie warto, zobacz moją odpowiedź, jak to zrobić o wiele łatwiej w czystym (ish) bashu.