forループのglob演算子に関する問題

forループのglob演算子に関する問題

/homeディレクトリ内のすべてのファイルを繰り返し繰り返そうとします。各ファイルでいくつかのLinuxコマンドを実行したいと思います。だから私は次のようなforループを使用しています。

for i in /home/**/*

また、次の文でスクリプトを起動します。

  • shopt -s グロスター
  • shopt -s nullglob

しかし、forループに閉じ込められます。あまりにも多くのファイルを処理するのに問題がある可能性があります。 forループに別のディレクトリ(ファイル数が少ない)を指定すると、正しく渡されます。

また何を試すことができますか?

完全なコード:

#!/bin/bash

shopt -s globstar
shopt -s nullglob
echo "ggg"
for i in /home/**/*
do
    NAME=${i}
    echo "It's there." $NAME
    if [ -f "$i" ]; then
        echo "It's there." $NAME
        printf "\n\n"
    fi
done

答え1

シェルには拡張モードが必要です/home/**/* 完全ループの最初の繰り返しを開始する前に。ファイルが多い場合は、サイクルが実際に開始されるまで自然に時間がかかります。この例では、シェルプロセスを観察すると、topその下にあるすべてのファイルとディレクトリのリストが作成されるにつれて、メモリ消費が徐々に増加することがわかります/home

ディレクトリ構造内の一般的なファイル数を数えるには、を使用するのが最善ですfind

find /home -type f -printf '\n' | wc -l

これにより、下の各一般ファイルに対して 1 行の出力が印刷され、行数が計算され、最後に合計が与えられます/homewc

隠しファイルを防ぐには:

find /home ! -name '.*' -type f -printf '\n' | wc -l

また、ディレクトリを隠さないでください(シェルループもこれを行います)。

find /home -name '.*' -prune -o -type f -printf '\n' | wc -l

wc -l出力でパス名を計算するのではなく空行を計算する理由-printは、パス名に改行文字を含めることができます。この場合、wc -l計算エラーが発生する可能性があるためです。


シンボリックリンクについて:シェルループはシンボリックリンクに従い、シンボリックリンクされたディレクトリがある場合はループがそのディレクトリに入り、通常のファイルを指すシンボリックリンクがある場合、ループはそのディレクトリを計算します。

上記の解決策findいいえシンボリックリンクに従ってください。この-Lオプションを使用してfind同様の動作を得ることができます。

find -L /home -type f -printf '\n' | wc -l

GNUユーザー以外のユーザーもfind使用できます。-exec echo \;-printf '\n'

関連情報