Bash-Skript zum Umbenennen von Dateien basierend auf der Größe

Bash-Skript zum Umbenennen von Dateien basierend auf der Größe

Ich habe ein Bash-Skript, das Dateien in einem Ordner entsprechend der Eingabe aus einer Eingabeaufforderung umbenennt:

echo "Please rename and press enter" read rename 

if [ -z "$rename" ]; then 
  printf "no caption was selected, aborting!\n"
  exit 1
fi 

printf "rename is $rename\n" count=1

for i in *.jpg; do 
  j=printf "%04d" $count
  j="$rename"$j".jpg"
  count=$((count + 1))
  mv "$i" $j
done  
fi 
shift 
done

Wie kann ich dieses Skript ändern, sodass die Dateien im Ordner entsprechend ihrer Größe umbenannt werden?

Wenn ich die Dateien nach Größe sortiere, sehen sie im Ordner folgendermaßen aus:

a009      978kb
a001      567kb
a003      499kb
a008      432kb

Daher möchte ich, dass die resultierenden Dateien umbenannt werden:

a001      978kb
a002      567kb
a003      499kb
a004      432kb

Antwort1

Etwas wie das:

echo "Please rename and press enter"
read rename 

ls |
  # prepend filename with file size in bytes
  parallel stat -c %s,,sep,,%n --  |
  # sort by number
  sort -n |
  # rename to sequencenumber followed by size in bytes
  parallel -q --colsep ,,sep,, mv {2} "$rename"{#}_{1}

Antwort2

Der Haupttrick besteht darin, zu ersetzen

    for i in *.jpg

mit

    for i in $(ls -S *.jpg)

Wie Kusalananda jedoch anmerkt, setzt dies „gebildete“ Dateinamen (keine Leerzeichen, keine Steuerzeichen) voraus. Daher hier ein anderer Ansatz:

count=1
ls -S --escape *.jpg | while read f; do
    n=$(printf "%04d" $count)
    ((count++))
    mv --no-clobber "$f" "$rename$n.jpg"
done

-Ssortiert nach abnehmender Dateigröße
--escapeverhindert, dass Namen mit eingebetteten Zeilenumbrüchen Schäden verursachen
--no-clobberverhindert, dass Zieldateien überschrieben werden, falls das Skript zweimal ausgeführt wird

PS: Die Antwort von Ole Tange ist eine sehr schöne und effiziente Möglichkeit, dasselbe zu tun, aber Sie werden den Unterschied wahrscheinlich nicht bemerken, wenn Sie nicht routinemäßig Tausende von Dateien umbenennen.

Antwort3

In der zshShell:

typeset -Z 3 count=0
for name in *.jpg(.DNOL); do
    count=$(( count + 1 ))
    mv -i -- "$name" "a$count.jpg"
done

.jpgDies würde alle regulären Dateien mit einem Dateinamensuffix im aktuellen Verzeichnis in der Reihenfolge vom größten zum kleinsten durchlaufen . Für jede Datei würde es in umbenannt, aNNN.jpgwobei NNNdie mit Nullen gefüllte Ganzzahlanzahl der bisher verarbeiteten Dateien ist.

Der (.DNOL)Glob-Qualifizierer sortiert die passenden Dateinamen in der richtigen Reihenfolge mit OL(„revers order by length“) und wählt nur reguläre Dateien (einschließlich versteckter Namen) mit .D(„regular files, and dot-files“) aus. Dadurch Nwird das Muster ins Leere erweitert, wenn kein passender Name vorhanden ist („null glob“).

Dies würde mit allen gültigen Dateinamen auf jedem zshinstallierten Unix-System funktionieren.

So verwenden Sie dies von bash:

zsh -c 'typeset -Z 3 count=0
for name in *.jpg(.DNOL); do
    count=$(( count + 1 ))
    mv -i -- "$name" "a$count.jpg"
done'

Wenn Sie eine Variable haben $rename, die Sie als Dateinamenpräfix übergeben möchten, verwenden Sie stattdessen Folgendes a:

zsh -c 'typeset -Z 3 count=0
for name in *.jpg(.DNOL); do
    count=$(( count + 1 ))
    mv -i -- "$name" "$1$count.jpg"
done' zsh "$rename"

Beachten Sie, dass es zshsich bei der letzten Zeile nicht um einen Tippfehler handelt und dass der Wert wie im Skript $renameverwendet wird .$1zsh -c

verwandte Informationen