/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 行の出力が印刷され、行数が計算され、最後に合計が与えられます/home
。wc
隠しファイルを防ぐには:
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'