すべてのサブディレクトリを検査し、それらに含まれるファイルの数を報告する必要があります(さらに再帰することなく)。
directoryName1 numberOfFiles
directoryName2 numberOfFiles
すべてのサブディレクトリを検査し、それらに含まれるファイルの数を報告する必要があります(さらに再帰することなく)。
directoryName1 numberOfFiles
directoryName2 numberOfFiles
回答:
これは、安全でポータブルな方法で行われます。奇妙なファイル名で混乱することはありません。
for f in *; do [ -d ./"$f" ] && find ./"$f" -maxdepth 1 -exec echo \; | wc -l && echo $f; done
最初にファイル数を出力し、次に別の行にディレクトリ名を出力することに注意してください。OPのフォーマットを保持したい場合は、さらにフォーマットが必要です。例えば
for f in *; do [ -d ./"$f" ] && find ./"$f" -maxdepth 1 -exec echo \;|wc -l|tr '\n' ' ' && echo $f; done|awk '{print $2"\t"$1}'
興味のあるサブディレクトリの特定のセットがある場合*
、それらを置き換えることができます。
なぜこれが安全なのですか?(したがって、スクリプトに値する)
ファイル名には、を除く任意の文字を含めることができます/
。シェルまたはコマンドによって特別に処理されるいくつかの文字があります。それらにはスペース、改行、ダッシュが含まれます。
for f in *
コンストラクトを使用すると、内容に関係なく、各ファイル名を安全に取得できます。
変数にファイル名を設定しても、のようなことは避けなければなりませんfind $f
。場合は$f
、ファイル名が含まれて-test
、find
あなたはそれを与えたオプションに文句を言うでしょう。これを回避する方法./
は、名前の前に使用することです。このように、それは同じ意味を持ちますが、もはやダッシュで始まりません。
改行とスペースも問題です。$f
ファイル名として「hello、buddy」が含まれている場合find ./$f
、はfind ./hello, buddy
です。あなたは言っているfind
を見て./hello,
とbuddy
。それらが存在しない場合、文句を言い、決して覗き込むことはありません./hello, buddy
。これは簡単に回避できます-変数を引用符で囲みます。
最後に、ファイル名には改行を含めることができるため、ファイル名のリスト内の改行のカウントは機能しません。改行を使用すると、すべてのファイル名に対して追加のカウントが得られます。これを回避するには、ファイルのリストで改行をカウントしないでください。代わりに、単一のファイルを表す改行(またはその他の文字)をカウントします。理由はここにありfind
、コマンドは、単に持っていません。ファイルを集計する目的で、新しい行を1行だけ印刷したい。-exec echo \;
-exec echo {} \;
-mindepth 1
-printf '\n'
代わりに使用することもできます-exec echo
。
-printf
たとえばFreeBSDで動作させたい場合はできません。
標準のLinuxソリューションを探していると仮定すると、これを達成する比較的簡単な方法はfind
次のとおりです。
find dir1/ dir2/ -maxdepth 1 -type f | wc -l
find
指定された2つのサブディレクトリをトラバースする場所-maxdepth
。1に設定すると、さらなる再帰が防止-type f
され、改行で区切られたファイル()のみが報告されます。次に、結果がパイプされwc
て、それらの行の数がカウントされます。
find . -maxdepth 1 -type d
出力をどのように組み合わせることができますか?
find $dirs ...
か、または(b)それらが1つ上のレベルのディレクトリのみにある場合、そのディレクトリからのグロブのいずれかfind */ ...
-exec echo
findコマンドに追加します-ファイル名をエコーせず、改行のみをエコーします。
「再帰なし」とは、次の場合 directoryName1
サブディレクトリが、サブディレクトリ内のファイルをカウントしたくないですか?その場合、指定されたディレクトリ内のすべての通常ファイルをカウントする方法は次のとおりです。
count=0
for d in directoryName1 directoryName2; do
for f in "$d"/* "$d"/.[!.]* "$d"/..?*; do
if [ -f "$f" ]; then count=$((count+1)); fi
done
done
ことに注意してください -f
テストは2つの機能を実行する上記のグロブのいずれかと一致するエントリが通常のファイルかどうかをテストし、エントリが一致したかどうかをテストします(グロブのいずれかが何も一致しない場合、パターンはそのまま残ります¹)。あなたは関係なく、自分の型の指定されたディレクトリ内のすべてのエントリをカウントしたい場合は、交換してください-f
と-e
。
Kshには、パターンをドットファイルに一致させ、パターンに一致するファイルがない場合に空のリストを作成する方法があります。したがって、kshでは、次のように通常のファイルをカウントできます。
FIGNORE='.?(.)'
count=0
for x in ~(N)directoryName1/* ~(N)directoryName2/*; do
if [ -f "$x" ]; then ((++count)); fi
done
または、次のようなすべてのファイル:
FIGNORE='.?(.)'
files=(~(N)directoryName1/* ~(N)directoryName2/*)
count=${#files}
Bashには、これを簡単にするさまざまな方法があります。通常のファイルを数えるには:
shopt -s dotglob nullglob
count=0
for x in directoryName1/* directoryName2/*; do
if [ -f "$x" ]; then ((++count)); fi
done
すべてのファイルをカウントするには:
shopt -s dotglob nullglob
files=(directoryName1/* directoryName2/*)
count=${#files}
いつものように、zshではさらに簡単です。通常のファイルを数えるには:
files=({directoryName1,directoryName2}/*(DN.))
count=$#files
変化する (DN.)
して(DN)
、すべてのファイルをカウントします。
¹ 各パターンがそれ自体と一致することに注意してください。そうしないと、結果がオフになる可能性があります(たとえば、数字で始まるファイルをカウントしている場合、for x in [0-9]*; do if [ -f "$x" ]; then …
というファイルがある可能性があるため、できません[0-9]foo
)。
countスクリプト、Shawnの答え、および改行を含むファイル名でも使用可能な形式で1行に印刷されるようにするBashトリックに基づきます。
for f in *
do
if [ -d "./$f" ]
then
printf %q "$f"
printf %s ' '
find "$f" -maxdepth 1 -printf x | wc -c
fi
done
printf %q
文字列の引用バージョンを印刷することです。つまり、Bashスクリプトに入れて(潜在的に)改行やその他の特殊文字を含むリテラル文字列として解釈できる単一行文字列です。たとえば、echo -n $'\tfoo\nbar'
vsをprintf %q $'\tfoo\nbar'
。
このfind
コマンドは、ファイルごとに単一の文字を出力し、行をカウントする代わりにそれらをカウントするだけで機能します。
for i in `ls -1`; do echo $i : `ls -1 $i|wc -l`; done
find
Bashが行うのに、なぜ使用したいのですか?(shopt -s dotglob; for dir in */; do all=("$dir"/*); echo "$dir: ${#all[@]}"; done)
:すべてのディレクトリについて、そのディレクトリ内のエントリの数をカウントします(隠しドットファイルを含む、.
およびを除く..
)