Wie speichere ich Dateiinformationen in einem Array?

Wie speichere ich Dateiinformationen in einem Array?

Mit diesem Teil des Skripts kann ich die erforderlichen Informationen über Dateien in meinem Verzeichnis (und Unterverzeichnissen) abrufen. Die einzigen Informationen, die ich benötige, sind die Erweiterung und die Größe der Datei.

for file in `find . -type f`; do
   size=$(stat -c '%s' ${file})
   file=$(echo "${file}" | awk -F/ '{print $NF}')
   ext=$(echo "${file}" | grep '..*\.' | awk -F. '{print $NF}' | grep '[A-Za-z0-9]')
if [ -z ${ext} ]; then
   echo "NOTE: no extention"
else
   EXTS="${EXTS}${ext}${newLine}"

Es ist nur ein Teil des Skripts. Meine Frage ist also: Wie kann ich diese Informationen in ein Array einfügen? Ich meine, ich möchte ein Array mit Elementen, die so aussehen:

 c/123 /12 h/90 /0 txt/0

wobei c, h und txt die Dateierweiterungen und 123, 12 und 0 die Dateigrößen sind.
Ich hoffe, ich kann jetzt getrennt mit Größen und Erweiterungen arbeiten, ich habe meine Frage ordentlich formuliert. Entschuldigung für die Fehler. :)

Antwort1

Erste,tu es nichtfor file in $(find …). Das ist sehr zerbrechlich.

Jetzt können Sie Ihren Code etwas vereinfachen, indem Sie find so veranlassen, die Dateinamen und -größen gemeinsam auszugeben, und zwar mit -printf:

find . -type f -printf '%s.%f/'

Anschließend können Sie awkdiese Ausgabe verarbeiten, um kumulative Größen nach Erweiterung zu erhalten. Beachten Sie, dass ich .den Dateinamen ( %f) von der Größe ( ) getrennt habe und danach %sein hinzugefügt habe . Daher kann ich als Feldtrennzeichen in verwenden . Und da die einzigen in Dateinamen nicht zulässigen Zeichen und das ASCII-NUL sind, kann ich es bedenkenlos als Datensatztrennzeichen verwenden./.awk//

Also:

awk -F. -v RS=/ 'NF > 2 {size[$NF] += $1; next}
  {size["/"] += $1}
END {for (i in size) {print i,"/",size[i]}'

Hier verwende ich /als Index, wenn keine Erweiterung vorhanden ist.

Kombiniert:

$ find . -type f -printf '%s.%f/' | awk -F. -v RS=/ 'NF > 2 {size[$NF] += $1; next}
{size["/"] += $1}
END {for (i in size) {printf "%s/%d\n", i, size[i]}}'
h/780
md/2509
tex/23961
c/13557
//5109
txt/2349291
sh/1166
py/12248

Wenn Ihre Erweiterungen keine Leerzeichen enthalten, können Sie einfach Folgendes tun:

my_array=( $(find . -type f -printf '%s.%f/' | awk -F. -v RS=/ 'NF > 2 {size[$NF] += $1; next} {size["/"] += $1} END {for (i in size) {printf "%s/%d\n", i, size[i]}}') )

Oder Sie können die Prozesssubstitution verwenden und jeden Eintrag einlesen in:

my_arr=()
while IFS='' read -r entry
do
    my_arr+=( "$entry" )
done < <(find . -type f -printf '%s.%f/' | awk -F. -v RS=/ 'NF > 2 {size[$NF] += $1; next} {size["/"] += $1} END {for (i in size) {printf "%s/%d\n", i, size[i]}}')

Wie vorher:

$ printf "%s\n" "${my_arr[@]}"
h/780
md/2509
tex/23961
c/13557
//5109
txt/2349291
sh/1166
py/12248

Antwort2

Hier ist ein kurzes Bash-Skript, das diese Aufgabe erledigt:

i=0
while read -r -d $'\0' file
do
   size=$(stat -c '%s' ${file})
   ext=`basename $file | sed -re "s/^[^.]+.*\.//"`

   if [ -z "$ext" ] || [ "$ext" = "`basename $file`" ] ; then
      echo "NOTE: no extention ($file)"
   else
     extensions[$i]="$ext"
     sizes[$((i++))]=$size
   fi
done < <(find . -type f -print0)

for (( j=0 ; j<i; j++ )) do
  echo index: $j / extension: ${extensions[$j]} / size: ${sizes[$j]}
done

verwandte Informationen