シェルスクリプトから、ディレクトリにファイルが含まれているかどうかを確認するにはどうすればよいですか?
これに似たもの
if [ -e /some/dir/* ]; then echo "huzzah"; fi;
ただし、ディレクトリに1つまたは複数のファイルが含まれている場合に機能します(上記のファイルは0または1個のファイルでのみ機能します)。
シェルスクリプトから、ディレクトリにファイルが含まれているかどうかを確認するにはどうすればよいですか?
これに似たもの
if [ -e /some/dir/* ]; then echo "huzzah"; fi;
ただし、ディレクトリに1つまたは複数のファイルが含まれている場合に機能します(上記のファイルは0または1個のファイルでのみ機能します)。
回答:
これまでの解決策はを使用していますls
。ここにすべてのbashソリューションがあります:
#!/bin/bash
shopt -s nullglob dotglob # To include hidden files
files=(/some/dir/*)
if [ ${#files[@]} -gt 0 ]; then echo "huzzah"; fi
shopt -q nullglob || resetnullglob=1; shopt -s nullglob; shopt -q dotglob || resetdotglob=1; shopt -s dotglob; files=(/some/dir/*); [ "$files" ] && echo "wowzers"; [ "$resetdotglob" ] && shopt -u dotglob; [ "$resetnullglob" ] && shopt -u nullglob;
files=$(shopt -s nullglob;shopt -s dotglob;echo /some/dir/*)
files=$(shopt -s nullglob;shopt -s dotglob;echo /some/dir/*)
いる場合:ifステートメントは次のように変更するif [ ${#files} -gt 0 ];
必要があります。files=($(shopt -s nullglob;shopt -s dotglob;echo /some/dir/*))
shopt -s nullglob dotglob; f=your/dir/*; ((${#f}))
このトリックは100%でbash
、サブシェルを起動(スポーン)します。このアイデアはBruno De Fraineによるもので、teambobのコメントによって改善されました。
files=$(shopt -s nullglob dotglob; echo your/dir/*)
if (( ${#files} ))
then
echo "contains files"
else
echo "empty (or does not exist or is a file)"
fi
注:空のディレクトリと存在しないディレクトリの違いはありません(提供されたパスがファイルの場合でも)。
#bash IRCチャネルの「公式」 FAQに同様の代替案と詳細(および例)があります。
if (shopt -s nullglob dotglob; f=(*); ((${#f[@]})))
then
echo "contains files"
else
echo "empty (or does not exist, or is a file)"
fi
[ -n "$(ls -A your/dir)" ]
このトリックは、2007年に投稿されたnixCraftの記事からインスピレーションを得てい2>/dev/null
ます"No such file or directory"
。追加して、出力エラーを抑制します。Andrew Taylorの回答(2008)とgr8can8dianの回答(2011)
も参照してください。
if [ -n "$(ls -A your/dir 2>/dev/null)" ]
then
echo "contains files (or is a file)"
else
echo "empty (or does not exist)"
fi
または1行のバシズムバージョン:
[[ $(ls -A your/dir) ]] && echo "contains files" || echo "empty"
注: ディレクトリが存在しない場合にls
戻ります$?=2
。しかし、ファイルと空のディレクトリの間に違いはありません。
[ -n "$(find your/dir -prune -empty)" ]
この最後のトリックは、からインスピレーションを得ているgravstarの答え-maxdepth 0
に置き換えられ-prune
とすることにより改善PHILSのコメント。
if [ -n "$(find your/dir -prune -empty 2>/dev/null)" ]
then
echo "empty (directory or file)"
else
echo "contains files (or does not exist)"
fi
を使用したバリエーション-type d
:
if [ -n "$(find your/dir -prune -empty -type d 2>/dev/null)" ]
then
echo "empty directory"
else
echo "contains files (or does not exist or is not a directory)"
fi
説明:
find -prune
よりfind -maxdepth 0
少ない文字を使用するのと同じですfind -empty
空のディレクトリとファイルを出力しますfind -type d
ディレクトリのみを出力します注:[ -n "$(find your/dir -prune -empty)" ]
以下の短縮バージョンで置き換えることもできます。
if [ `find your/dir -prune -empty 2>/dev/null` ]
then
echo "empty (directory or file)"
else
echo "contains files (or does not exist)"
fi
この最後のコードはほとんどの場合に機能しますが、悪意のあるパスがコマンドを表す可能性があることに注意してください...
[ -n "$(find "your/dir" -prune -empty)" ]
、ディレクトリパスの繰り返しを回避できると思います。
if [ ``ls -A your/dir`` ]
スクリプトで使用しているときに、0、1、または2つのサブディレクトリがあるディレクトリでは正常に機能するが、2つより多いサブディレクトリを持つディレクトリでは機能しないという結論に達しました。line 17: [: 20150424-002813: unary operator expected
ここ20150424-002813
で、ディレクトリ名の1つでした。使用したシェルはでした/bin/bash/
。ようやく変更しましたls "$destination" | tail -1
if [ ``ls -A my/dir`` ]
はエラーで終了しますbash: [: -A: binary operator expected
。bashバージョン4.1.2および4.2.53でテスト済み。
-n
バリアントは見出しにありましたが、次の段落にはありませんでした)。だから、はい、それは結構です。
ls: cannot access '/path': No such file or directory
ます。このメッセージを抑制する方法はありますか?そこで静かに失敗したいと思います。
次はどうですか:
if find /some/dir/ -maxdepth 0 -empty | read v; then echo "Empty dir"; fi
この方法では、ディレクトリの内容の完全なリストを生成する必要はありません。read
両方の出力を破棄し、何かが読み込まれたときにのみtrueと評価表現を作ることである(すなわち/some/dir/
では空発見されましたfind
)。
find /some/dir/ -maxdepth 0 -empty -exec echo "huzzah" \;
-maxdepth
および-empty
プライマリに依存しています。
試してください:
if [ ! -z `ls /some/dir/*` ]; then echo "huzzah"; fi
/bin/ls <some_dir>/* 2> /dev/null
if [!-z "$ tmp"]; その後、Something is there fiをエコーします
ls /some/dir/*
]; 次に「huzzah」をエコーします。fi
-n
代わりに使用できます! -z
(どちらも同等ですが、存在する場合は短い形式を使用しないでください)。
BigGray% if [ ! -z
ls / some / dir / * `]; 次に「huzzah」をエコーします。fi zsh:一致が見つかりません:/ some / dir / * `
ls...
bashで二重引用符がないと、私にはうまくいきません
# Works on hidden files, directories and regular files
### isEmpty()
# This function takes one parameter:
# $1 is the directory to check
# Echoes "huzzah" if the directory has files
function isEmpty(){
if [ "$(ls -A $1)" ]; then
echo "huzzah"
else
echo "has no files"
fi
}
DIR="/some/dir"
if [ "$(ls -A $DIR)" ]; then
echo 'There is something alive in here'
fi
#ディレクトリに隠しファイルが含まれているかどうかを確認します。 # #使用法:空の場合 "$ HOME"; 次に、「お帰りなさい」とエコーします。fi # isempty(){ $ 1 / *の_iefの場合; 行う if [-e "$ _ief"]; その後 戻る1 fi できた 0を返す }
実装に関する注意事項:
for
ループは、外部への呼び出しを回避ls
プロセスを。それでも、すべてのディレクトリエントリが一度読み込まれます。これは、readdir()を明示的に使用するCプログラムを作成することによってのみ最適化できます。test -e
ループの内側は、空のディレクトリの場合をキャッチします。この場合、変数に_ief
は値「somedir / *」が割り当てられます。そのファイルが存在する場合のみ、関数は「空でない」を返しますtest
実装は-e
フラグをサポートしていません。dotglob
設定されていない場合、ディレクトリ内のドットファイルは無視されますshopt -s dotglob
これにより、ディレクトリが空であるかどうか、または空でない場合は、そこに含まれるファイルの数がわかります。
directory="/some/dir"
number_of_files=$(ls -A $directory | wc -l)
if [ "$number_of_files" == "0" ]; then
echo "directory $directory is empty"
else
echo "directory $directory contains $number_of_files files"
fi
ls
ためです。
これは本当に遅い応答かもしれませんが、これが機能する解決策です。この行はファイルの存在のみを認識します!ディレクトリが存在する場合、誤検知は発生しません。
if find /path/to/check/* -maxdepth 0 -type f | read
then echo "Files Exist"
fi
dir_is_empty() {
[ "${1##*/}" = "*" ]
}
if dir_is_empty /some/dir/* ; then
echo "huzzah"
fi
あなたが名前のファイルがありませんと仮定*
には/any/dir/you/check
、それが上で動作するはずですbash
dash
posh
busybox sh
し、zsh
しかし(zshのため)が必要ですunsetopt nomatch
。
パフォーマンスは、(glob)ls
を使用するものに匹敵するはず*
です。多くのノードがあるディレクトリでは遅くなると思い/usr/bin
ます(3000以上のファイルがある場合はそれほど遅くはありませんでした)、すべてのディレクトリ/ファイル名(およびその他)を割り当てるのに十分なメモリを使用しますそれらはすべて引数として関数に渡される(解決される)ため、一部のシェルではおそらく引数の数や引数の長さ、あるいはその両方に制限があります。
ディレクトリが空であるかどうかを確認するポータブルで高速なO(1)ゼロリソースの方法があれば便利です。
更新
上記のバージョンはis_empty
、Richのsh(POSIXシェル)トリックからのトリックなど、さらにテストが必要な場合に備えて、隠しファイル/ディレクトリを考慮していません。
is_empty () (
cd "$1"
set -- .[!.]* ; test -f "$1" && return 1
set -- ..?* ; test -f "$1" && return 1
set -- * ; test -f "$1" && return 1
return 0 )
しかし、代わりに、私はこのようなものについて考えています:
dir_is_empty() {
[ "$(find "$1" -name "?*" | dd bs=$((${#1}+3)) count=1 2>/dev/null)" = "$1" ]
}
悲しいことに、私の上、dirが空の場合、引数と検索出力からのスラッシュの違いを末尾に、改行を末尾に(これはハンドルに簡単にする必要があります)に関するいくつかの懸念busybox
sh
におそらくバグであるかを示すfind -> dd
出力とパイプは(randomically切り捨て私が使用しcat
た場合、出力は常に同じですがdd
、引数を持つようですcount
)。
is_empty(){ [ ! -d "${1}" ] && return 2;set -- "${1}" "${1}"/* "${1}"/.[!.]* "${1}"/..?*;[ "${*}" = "${1} ${1}/* ${1}/.[!.]* ${1}/..?*" ]; };
私は質問がbashにマークされたことを知っています。ただし、参考までに、zshユーザーの場合:
がfoo
空でないかどうかを確認するには:
$ for i in foo(NF) ; do ... ; done
ここで、foo
が空でない場合、for
ブロック内のコードが実行されます。
foo
空かどうかを確認するには:
$ for i in foo(N/^F) ; do ... ; done
foo
空の場合、for
ブロック内のコードが実行されます。
foo
上記のディレクトリを引用する必要はありませんでしたが、必要に応じて引用することができます。
$ for i in 'some directory!'(NF) ; do ... ; done
ディレクトリでなくても、複数のオブジェクトをテストできます。
$ mkdir X # empty directory
$ touch f # regular file
$ for i in X(N/^F) f(N/^F) ; do echo $i ; done # echo empty directories
X
ディレクトリでないものはすべて無視されます。
グロブを使用しているので、任意のグロブ(またはブレース展開)を使用できます。
$ mkdir X X1 X2 Y Y1 Y2 Z
$ touch Xf # create regular file
$ touch X1/f # directory X1 is not empty
$ touch Y1/.f # directory Y1 is not empty
$ ls -F # list all objects
X/ X1/ X2/ Xf Y/ Y1/ Y2/ Z/
$ for i in {X,Y}*(N/^F); do printf "$i "; done; echo # print empty directories
X X2 Y Y2
配列に配置されたオブジェクトを調べることもできます。上記のディレクトリを使用すると、たとえば次のようになります。
$ ls -F # list all objects
X/ X1/ X2/ Xf Y/ Y1/ Y2/ Z/
$ arr=(*) # place objects into array "arr"
$ for i in ${^arr}(N/^F); do printf "$i "; done; echo
X X2 Y Y2 Z
したがって、配列パラメーターに既に設定されている可能性のあるオブジェクトをテストできます。
for
ブロック内のコードは、明らかに、すべてのディレクトリで順番に実行されることに注意してください。これが望ましくない場合は、単純に配列パラメーターを設定して、そのパラメーターを操作できます。
$ for i in *(NF) ; do full_directories+=($i) ; done
$ do_something $full_directories
zshユーザーの場合、(F)
glob修飾子(を参照man zshexpn
)があり、これは「フル」(空ではない)ディレクトリに一致します。
$ mkdir X Y
$ touch Y/.f # Y is now not empty
$ touch f # create a regular file
$ ls -dF * # list everything in the current directory
f X/ Y/
$ ls -dF *(F) # will list only "full" directories
Y/
修飾子(F)
は、一致するオブジェクトをリストします。ディレクトリであり、かつ空ではありません。したがって、(^F)
一致します。ディレクトリではない、または空です。したがって、(^F)
たとえば、通常のファイルだけをリストすることもできます。したがって、zshexp
manページで説明されているように、(/)
ディレクトリのみをリストするglob修飾子も必要です。
$ mkdir X Y Z
$ touch X/f Y/.f # directories X and Y now not empty
$ for i in *(/^F) ; do echo $i ; done
Z
したがって、特定のディレクトリが空かどうかを確認するには、次のように実行します。
$ mkdir X
$ for i in X(/^F) ; do echo $i ; done ; echo "finished"
X
finished
そして、空でないディレクトリがキャプチャされないことを確認するために:
$ mkdir Y
$ touch Y/.f
$ for i in Y(/^F) ; do echo $i ; done ; echo "finished"
zsh: no matches found: Y(/^F)
finished
おっとっと!Y
は空ではないので、zshは(/^F)
(「空のディレクトリ」)に一致するものを見つけず、グロブに一致するものが見つからなかったことを示すエラーメッセージを出力します。したがって、(N)
グロブ修飾子を使用して、これらの考えられるエラーメッセージを抑制する必要があります。
$ mkdir Y
$ touch Y/.f
$ for i in Y(N/^F) ; do echo $i ; done ; echo "finished"
finished
したがって、空のディレクトリの場合、修飾子が必要です。修飾子は(N/^F)
、「エラーについて警告しないでください。ディレクトリがいっぱいではありません」。
同様に、空でないディレクトリの場合は、修飾子が必要です(NF)
。これは、「失敗について警告しないでください。ディレクトリ全体」と同様に読み取ることができます。
空のディレクトリに関するwooledgeガイドが言及されていないことに驚いています。このガイド、そしてすべてのwooledgeは、シェルタイプの質問には必読です。
そのページからの注目:
ls出力を解析しようとしないでください。ls -Aソリューションでさえ壊れる可能性があります(たとえば、HP-UXでは、rootの場合、ls -Aはrootでない場合とは正反対のことを行います-そして、私は信じられないほどの何かを作ることができません愚か)。
実際、直接的な質問を完全に避けたいと思うかもしれません。通常、人々はその中のファイルを含む何かをしたいので、ディレクトリが空であるかどうか知りたいです。たとえば、次の検索ベースの例のいずれかが適切な解決策になる場合があります。
# Bourne
find "$somedir" -type f -exec echo Found unexpected file {} \;
find "$somedir" -maxdepth 0 -empty -exec echo {} is empty. \; # GNU/BSD
find "$somedir" -type d -empty -exec cp /my/configfile {} \; # GNU/BSD
最も一般的には、本当に必要なのは次のようなものです:
# Bourne
for f in ./*.mpg; do
test -f "$f" || continue
mympgviewer "$f"
done
言い換えると、質問をしている人は、mympgviewer:./*.mpg:No such file or directory no実際にはそのようなテストが必要ないのに、明示的な空のディレクトリテストが必要だと思ったかもしれません。
olibreの答えからヒント(またはいくつか)を取ると、Bash関数が好きです。
function isEmptyDir {
[ -d $1 -a -n "$( find $1 -prune -empty 2>/dev/null )" ]
}
それは1つのサブシェルを作成する一方で、私が想像できるほどO(1)ソリューションに近く、それに名前を付けると読みやすくなります。その後、私は書くことができます
if isEmptyDir somedir
then
echo somedir is an empty directory
else
echo somedir does not exist, is not a dir, is unreadable, or is not empty
fi
O(1)については異常値のケースがあります。大きなディレクトリで最後または最後のエントリを除くすべてが削除されている場合、「検索」ですべてを読み取って、空かどうかを判断する必要があります。期待されるパフォーマンスはO(1)であると思いますが、最悪の場合はディレクトリサイズに比例します。私はこれを測定していません。
これまでのところ、grepを使用してより簡単な答えを(おそらく奇妙な記号が多すぎないように)返す答えを見たことはありません。これは、bourneシェルを使用してディレクトリにファイルが存在するかどうかを確認する方法です。
これは、ディレクトリ内のファイル数を返します。
ls -l <directory> | egrep -c "^-"
ディレクトリが書き込まれる場所にディレクトリパスを入力できます。パイプの前半は、各ファイルの出力の最初の文字が「-」であることを確認します。次にegrepは、正規表現を使用して、その記号で始まる行数をカウントします。今あなたがしなければならないすべてはあなたが得た数を保存し、次のような逆引用符を使ってそれを比較することです:
#!/bin/sh
fileNum=`ls -l <directory> | egrep -c "^-"`
if [ $fileNum == x ]
then
#do what you want to do
fi
xは任意の変数です。
bashによる簡単な答え:
if [[ $(ls /some/dir/) ]]; then echo "huzzah"; fi;
私は行きfind
ます:
if [ -z "$(find $dir -maxdepth 1 -type f)" ]; then
echo "$dir has NO files"
else
echo "$dir has files"
これにより、サブディレクトリを経由せずに、ディレクトリ内のファイルのみを探す出力がチェックされます。次に、以下の-z
オプションを使用して出力を確認しますman test
。
-z STRING
the length of STRING is zero
いくつかの結果を見る:
$ mkdir aaa
$ dir="aaa"
空のディレクトリ:
$ [ -z "$(find aaa/ -maxdepth 1 -type f)" ] && echo "empty"
empty
それに夢中です:
$ mkdir aaa/bbb
$ [ -z "$(find aaa/ -maxdepth 1 -type f)" ] && echo "empty"
empty
ディレクトリ内のファイル:
$ touch aaa/myfile
$ [ -z "$(find aaa/ -maxdepth 1 -type f)" ] && echo "empty"
$ rm aaa/myfile
サブディレクトリ内のファイル:
$ touch aaa/bbb/another_file
$ [ -z "$(find aaa/ -maxdepth 1 -type f)" ] && echo "empty"
empty
いくつかの回避策があれば、ディレクトリにファイルがあるかどうかを確認する簡単な方法を見つけることができます。これは、特に.xmlファイルや.txtファイルなどをチェックするgrepコマンドでさらに拡張できます。例:ls /some/dir | grep xml | wc -l | grep -w "0"
#!/bin/bash
if ([ $(ls /some/dir | wc -l | grep -w "0") ])
then
echo 'No files'
else
echo 'Found files'
fi
if ls /some/dir/* >/dev/null 2>&1 ; then echo "huzzah"; fi;
nullglob
ため、を設定する場合はこれを使用しないように注意してくださいls
。
コマンドfindで試してください。ハードコーディングされたディレクトリを、または引数として指定します。次に、検索を開始して、ディレクトリ内のすべてのファイルを検索します。findの戻り値がnullかどうかを確認します。findのデータをエコーする
#!/bin/bash
_DIR="/home/user/test/"
#_DIR=$1
_FIND=$(find $_DIR -type f )
if [ -n "$_FIND" ]
then
echo -e "$_DIR contains files or subdirs with files \n\n "
echo "$_FIND"
else
echo "empty (or does not exist)"
fi
私は嫌いです ls - A
投稿され解決策がです。ほとんどの場合、削除したくないので、ディレクトリが空かどうかをテストします。以下はそれを行います。ただし、空のファイルをログに記録したいだけの場合は、無限のファイルをリストするよりも、確実に削除して再作成した方が早いですか?
これはうまくいくはずです...
if ! rmdir ${target}
then
echo "not empty"
else
echo "empty"
mkdir ${target}
fi
${target}/..
。
これは私にとってうまくいきます(dirが存在する場合):
some_dir="/some/dir with whitespace & other characters/"
if find "`echo "$some_dir"`" -maxdepth 0 -empty | read v; then echo "Empty dir"; fi
フルチェックで:
if [ -d "$some_dir" ]; then
if find "`echo "$some_dir"`" -maxdepth 0 -empty | read v; then echo "Empty dir"; else "Dir is NOT empty" fi
fi