sedとwcをawkに置き換える方法は? (ディレクトリの名前の計算)

sedとwcをawkに置き換える方法は? (ディレクトリの名前の計算)

フォルダ内の要素数を計算したいです。私はそれについて考えた

function lsc { /bin/ls -l $1 | sed 1d | wc -l }

しかし、私は人々がこれらのパイプを減らし、余分なものをawk取り除いている方法を思い出しました。それで、あなたは何をしますか?grepsedawk

答え1

lssedまたははwc必要ありませんawk

パターンが拡張される名前の数を数えたい場合は、次のものを使用できます。

set -- *
echo "$#"

このsetコマンドは、位置引数(など)をパターンに一致する名前$1に設定します。これは自動的に特殊変数を設定された位置引数の数、すなわち与えられたパターンに一致する名前の数に設定します。$2*$#

bash名前付き配列を持つシェルでは、次のものを使用できます。

names=(*)
echo "${#names[@]}"

これは同様に機能しますが、配列の要素をnamesパターン拡張によって生成された名前に設定します*。変数拡張は${#names[@]}配列の要素数ですnames

これに関する問題の1つは、パターンが何も一致しない場合は拡張されていないため、数が1であることです(ディレクトリが空の場合でも)。シェルでこの問題を解決するには、bashとしてnullglobシェルオプションを設定しますshopt -s nullglob。このシェルオプションを設定すると、どのパターンとも一致しないパターンが完全に削除されます。

bash隠された名前の数を計算するには、にdotglobシェルオプションを設定しますshopt -s dotglob

bashあなたの機能は次のとおりです

lsc () (
    shopt -s nullglob
    set -- "$1"/*
    echo "$#"
)

( ... )nullglob呼び出しシェルで設定しないように関数本体で使用するように注意してください。

または次の場合/bin/sh

lsc () {
    set -- "$1"/*
    if [ -e "$1" ] || [ -L "$1" ]; then
        echo "$#"
    else
        echo 0
    fi
}

ここの文は、if最初の位置引数が(何も一致しないため)拡張されていないパターンではなく、実際のファイルの名前であることを保証します。 (-e「exists」)は私たちが数字を信頼するために真でなければなりません$#。間違っている場合は、名前がテストのシンボリックリンクを参照していることを確認してください-L。これが真であれば、パターンが拡張される最初のものは「死んだ」シンボリックリンク(存在しないファイルを指すシンボリックリンク)であることがわかり、$#それが正しいと信じています。両方のテストが失敗した場合、一致するものがないことがわかるので、出力はです0

答え2

まず、1行の関数定義が正しくありません。このキーワードがあることは、おそらくBashを使用していることを示します。これはfunctionman bash にあるものです:Shell Function Definitions

function name [()] compound-command [redirection]

そして複合コマンドとして定義された:

{ list; }

したがって、次のようにする必要があります。

function lsc { /bin/ls -l $1 | sed 1d | wc -l; }

しかし、技術的に正確であってもうまく動作しません。 なぜいいえ解析ls(および実行方法)?

次のように、awkを使用して特定のディレクトリにある複数のファイルとディレクトリを印刷できます。

awk 'END {print ARGC - 1}' *

ただし、*awkは、シェル拡張の引数の1つ以上がディレクトリの場合にエラーを表示します。

$ awk 'END {print ARGC - 1}' *
awk: warning: command line argument `dir1' is a directory: skipped

しかし、とにかく結果はまだ良いです。エラーを/ dev / nullにリダイレクトできます。

awk 'END {print ARGC - 1}' * 2>/dev/null

関連情報