ファイル情報を配列に保存するにはどうすればいいですか?

ファイル情報を配列に保存するにはどうすればいいですか?

スクリプトのこの部分を使用すると、ディレクトリ (およびサブディレクトリ) 内のファイルに関する必要な情報を取得できます。必要な情報は、ファイルの拡張子とサイズだけです。

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}"

これはスクリプトの一部にすぎません。質問は、この情報を配列に入れるにはどうしたらよいかということです。つまり、次のような要素を持つ配列が欲しいのです。

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

ここで、c、h、txt はファイル拡張子、123、12、0 はファイル サイズです。最近はサイズと拡張子を別々に扱えるようになりました。
質問をきちんとまとめられたと思います。間違いがあったらごめんなさい。:)

答え1

初め、しないでくださいfor file in $(find …)それはとても壊れやすいです。

ここで、次のようにして、find でファイル名とサイズを一緒に印刷することで、コードを少し簡略化できます-printf

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

次に、 を使用しawkてこの出力を処理し、拡張子ごとの累積サイズを取得できます。.ファイル名 ( %f) とサイズ ( %s) を区切るために を使用し、その後に を追加したことに注意してください。したがって、でフィールド区切り文字として/を使用できます。また、ファイル名で許可されていない文字はと ASCII NUL のみであるため、 をレコード区切り文字として安全に使用できます。.awk//

それで:

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

/ここでは、拡張子がない場合にインデックスとして使用しています。

組み合わせ:

$ 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

拡張子にスペースが含まれていない場合は、次のようにします。

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

または、プロセス置換を使用して、次の各エントリを読み取ることもできます。

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

従来通り:

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

答え2

以下は、この作業を実行する短い bash スクリプトです。

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

関連情報