Bash スクリプト: 空のディレクトリのテスト
ディレクトリにファイルが入っていないかどうかをテストしたい。もしそうならば、私はいくつかの処理をスキップします。
if [./* == "./*"]; then
echo "No new file"
exit 1
fi
以下を試してみました。
line 1: [: too many arguments
以下のエラーが出ます。
0x1&
解決策/代替案はありますか?
ディレクトリにファイルが入っていないかどうかをテストしたい。もしそうならば、私はいくつかの処理をスキップします。
if [./* == "./*"]; then
echo "No new file"
exit 1
fi
以下を試してみました。
line 1: [: too many arguments
以下のエラーが出ます。
0x1&
解決策/代替案はありますか?
if [-z "$(ls -A /path/to/dir)"]; then
echo "Empty"
else
echo "Not Empty"
fi
あと、ディレクトリが存在するかどうかを事前に確認しておくとかっこいいですね。
is_empty() {
test -e "$1/"* 2>/dev/null
case $? in
1) return 0 ;;
*) return 1 ;;
esac
}
これは、test
の後に複数の引数が与えられた場合、-e
ビルドインが 2 で終了するという事実を利用しています。まず、"$1"/*
の glob は bash によって展開されます。これにより、1つのファイルにつき1つの引数が与えられることになる。つまり、
test -e "$1"*
のアスタリスクは展開されないので、Shell は *
という名前のファイルを試すことに戻り、1 を返します。…ただし、*
という名前のファイルが実際に存在する場合は、アスタリスクが展開されてアスタリスクとなり、上記と同じ呼び出し、つまり test -e "dir/*"
が 0 を返すことになります(この点を指摘してくれた @TrueY に感謝します)。
ファイルが1つの場合、test -e "dir/file"
が実行され、0を返します。
しかし、ファイルが1よりも多い場合、test -e "dir/file1" "dir/file2"
が実行され、bashはそれを使用エラー、つまり2として報告します。
許可される引数の数よりも多くのファイルがあります。
あるいは、実際には空の名前のファイルが存在します。
これは、現在の作業ディレクトリ(.)で動作します:
[`ls -1A . | wc -l` -eq 0] && echo "Current dir is empty." || echo "Current dir has files (or hidden files) in it."
または、同じコマンドを3行に分割して読みやすくすることもできます。
[`ls -1A . | wc -l` -eq 0] && \
echo "Current dir is empty." || \
echo "Current dir has files (or hidden files) in it."
ls -1A . | wc -l
を ls -1A <target-directory> | wc -l
に置き換えて、別のターゲットフォルダで実行する必要がある場合は、-1a
を -1A
に置き換えてください。
Edit . 0x6& を 0x6& に置き換えました (@Daniel のコメント参照)
以下のように使います。
count="$( find /path -mindepth 1 -maxdepth 1 | wc -l )"
if [$count -eq 0] ; then
echo "No new file"
exit 1
fi
こうすることで、ls
の出力形式に依存しなくなります。-mindepth
はディレクトリ自体をスキップし、-maxdepth
はサブディレクトリへの再帰的な防御を防止して高速化を図ります。
配列を使用します。
files=( * .* )
if (( ${#files[@]} == 2 )); then
# contents of files array is (. ..)
echo dir is empty
fi
files=$(shopt -s nullglob; shopt -s dotglob; echo /MYPATH/*)
[["$files"]] || echo "dir empty"
thanks to https://stackoverflow.com/a/91558/520567
これは私の回答を匿名で編集したものです。わずかな変更でファイル数が表示されます。
files=$(shopt -s nullglob dotglob; s=(MYPATH/*); echo ${s[*]})
echo "MYPATH contains $files files"
これはファイル名にスペースが含まれていても正しく動作します。
if find "${DIR}" -prune ! -empty -exit 1; then
echo Empty
else
echo Not Empty
fi
EDIT: 実装を**簡単に*見てみたところ、この解決策はgnu findでも問題なく動作すると思います。しかし、これは例えば netbsd の find では動作しないかもしれません。実際、これは stat(2) の st_size フィールドを使っています。マニュアルには次のように記述されています。
st_size The size of the file in bytes. The meaning of the size
reported for a directory is file system dependent.
Some file systems (e.g. FFS) return the total size used
for the directory metadata, possibly including free
slots; others (notably ZFS) return the number of
entries in the directory. Some may also return other
things or always report zero.
より良い解決策は次のように記述されています:
if find "${DIR}" -mindepth 1 -exit 1; then
echo Empty
else
echo Not Empty
fi
また、最初の解決策の -prune は無駄です。
EDIT: gnu find では -exit がありません。GNU find では、これが動作するはずです。
if [-z "`find \"${DIR}\" -mindepth 1 -exec echo notempty \; -quit`"]; then
echo Empty
else
echo Not Empty
fi
スクリプトが../IN
ディレクトリにあることを考慮して、../Script
ディレクトリ内のファイルをチェックして処理するようにしました。
FileTotalCount=0
for file in ../IN/*; do
FileTotalCount=`expr $FileTotalCount + 1`
done
if test "$file" = "../IN/*"
then
echo "EXITING: NO files available for processing in ../IN directory. "
exit
else
echo "Starting Process: Found ""$FileTotalCount"" files in ../IN directory for processing."
# Rest of the Code
これはすべて素晴らしいものです - 現在のディレクトリの下に空のディレクトリがないかチェックできるように、スクリプトにしました。以下は'findempty'というファイルに入れて、どこかのパスに置いて、bashがそれを見つけられるようにして、chmod 755で実行します。あなたの特定のニーズに合わせて簡単に修正することができると思います。
#!/bin/bash
if ["$#" == "0"]; then
find . -maxdepth 1 -type d -exec findempty "{}" \;
exit
fi
COUNT=`ls -1A "$*" | wc -l`
if ["$COUNT" == "0"]; then
echo "$* : $COUNT"
fi
カレントディレクトリ以外のディレクトリについては、rmdir
を試すことで空かどうかを確認することができます。rmdir
が成功しても、実際には空のディレクトリがテストに耐えられるようにしたい場合は、再度 rmdir
を実行してください。
知っているディレクトリが一時的に存在しなくなることで、他のプロセスが混乱する可能性がある場合は、このハックを使用しないでください。
mkdir
がうまくいかず、大量のファイルを含む可能性のあるディレクトリをテストしている可能性がある場合、シェルのグロブに依存した解決策は遅くなったり、コマンドラインの長さに制限がかかったりする可能性があります。そのような場合は、rmdir
を使用した方が良いでしょう。私が考えられる最速のfind
ソリューションは、
is_empty() {
test -z $(find "$1" -mindepth 1 -printf X -quit)
}
これはGNUとBSDバージョンのfind
では動作しますが、find
演算子が一つ残らず欠落しているSolarisバージョンでは動作しません。オラクル、あなたの仕事を愛しています。