印刷する前にawkでコマンドを実行する

印刷する前にawkでコマンドを実行する

ディレクトリサイズの計算中にディレクトリを一覧表示し、単純なコマンドを使用してディレクトリ全体を印刷したいと思います。エルエスそしてアッ、リストと表示する内容を効果的に制御できます。

ls -AlhF /usr | awk '{print $6, $7, $8, "\011", $9 }'

ただし、さらに一歩進んでフォルダやファイルのサイズを確認するには、$ 9と次のコマンドを使用します。Du-sこのような:

ls -AlhF /usr | awk '{print $6, $7, $8, "\011", $9, du -s /usr/$9 }'

バックティックまたは二重引用符を使用してさまざまな方法で作成しようとしましたが、常にエラーや不要な結果が発生しました。

答え1

lsこの質問に答え、今は解析された出力に関する質問を無視してからコマンドの出力を取得するには、awk次のようにします。

cmd="that command"
output=""
while ((cmd | getline line) > 0)
  output = output line RS
status = close(cmd)

終了ステータスがエンコードされる方法状態変数はawk実装ごとに異なります。信頼できるのは、cmd成功した場合にのみゼロになるということです。

getlineコマンドラインを解析するには、シェル(通常はPOSIXシェルですが、一部のシステムではBourneシェルかもしれません)を起動します。したがって、その中にあるデータを正確に引用することが重要です。最も安全な一重引用符を使用するのが最善です。

ここで出力はとにかく1行なので(あなたのメソッドは改行はもちろん、空白文字を含むファイル名を処理することはできません)、次の1つだけを実行できますgetline

 awk -v q="'" '
   function shquote(s) {
     gsub(q, q "\\" q q, s)
     return q s q
   }
   {
     cmd = "du -sk " shquote("/usr/" $9)
     cmd | getline du_output
     status = close(cmd)
   }'

getline変数名なしで呼び出すと、$0ディスク使用量をより簡単に抽出できるように設定されます。

DIR=/usr export DIR
LC_ALL=C ls -l -- "$DIR" | awk -v q="'" '
  function shquote(s) {
    gsub(q, q "\\" q q, s)
    return q s q
  }
  {
    date = $6 " " $7 " " $8
    name = $9
    cmd = "du -sk " shquote(ENVIRON["DIR"] (ENVIRON["DIR"] ~ /^\/*$/ ? "" : "/") name)
    cmd | getline
    disk_usage = $1
    print date "\t" name "\t" disk_usage
  }'

答え2

ls -AlhF /usr | awk '{print "echo "$6" "$7" "$8" \011 "$9" $(du -s /usr/"$9")" }' | sh

awkを使用してechoコマンドとduコマンドをビルドし、shにパイプして実行します。

答え3

これはperl実装です。いいえ出力の解析ls -l(本質的に信頼できない)に依存し、必要な日付またはサイズの出力形式を使用するように簡単に変更できます。

ファイルに保存して実行可能にしてから始めます/path/to/script /usr。スクリプトには少なくとも1つのディレクトリ名引数が必要です。

#!/usr/bin/perl

use strict;
use Date::Format;

if ($#ARGV < 0) { die "Missing directory argument" };

foreach my $dir (@ARGV) {
    $dir =~ s:/+$::;  # strip trailing /
    opendir(my $dh, $dir) || die "Can't opendir $dir: $!";

    while (readdir $dh) {
      next if (m/^\.{1,2}$/); # skip . and .. entries

      my $mtime=(stat("$dir/$_"))[9];   # extract mtime field from stat
      my $mtime_f = time2str('%Y-%m-%d %X', $mtime);

      open(my $fh, "-|", 'du', '-s', '--', "$dir/$_");
      my $du = <$fh>;
      ($du) = split(' ',$du); # only want the first blank-separated field
      close($fh).

      printf "%s\t%s\t%s\n", $mtime_f, "$dir/$_" , $du;
    }

    closedir $dh;
};

これを行う簡単で短い方法(perl、awk、または他の言語を使用)がありますが、これはディレクトリとその内容に関する追加情報を報告するのに便利な基盤を提供します。perldoc -f statこの機能に使用できる情報の詳細については、を参照してくださいstat()

ちなみに、これはで達成できますが、独自の機能と日付書式設定機能をawk実装する必要があります。stat()使いやすく便利ですperl

GNUawkgawkロード可能なモジュールをサポートし、このfilefuncsモジュールは配列をstat()埋めるstatdata[]モジュールを提供します。スクリプトの上部に追加して@load "filefuncs"使用しますawk

関連情報