シェルスクリプト内にディレクトリが存在するかどうかを確認する
質問
シェルスクリプト内でディレクトリが存在するかどうかを確認するにはどのようなコマンドを使用できますか?
解決
シェル スクリプトにディレクトリが存在するかどうかを確認するには、次のコマンドを使用できます。
if [ -d "$DIRECTORY" ]; then
# Control will enter here if $DIRECTORY exists.
fi
または、ディレクトリが存在しないかどうかを確認するには、次のようにします。
if [ ! -d "$DIRECTORY" ]; then
# Control will enter here if $DIRECTORY doesn't exist.
fi
ただし、 ジョン・エリクソン 指摘されているように、ディレクトリへのシンボリック リンクもこのチェックに合格することを考慮しないと、後続のコマンドが意図したとおりに動作しない可能性があります。例えば。これを実行します:
ln -s "$ACTUAL_DIR" "$SYMLINK"
if [ -d "$SYMLINK" ]; then
rmdir "$SYMLINK"
fi
次のエラー メッセージが表示されます。
rmdir: failed to remove `symlink': Not a directory
したがって、後続のコマンドでディレクトリが必要な場合は、シンボリック リンクを別の方法で処理する必要がある場合があります。
if [ -d "$LINK_OR_DIR" ]; then
if [ -L "$LINK_OR_DIR" ]; then
# It is a symlink!
# Symbolic link specific commands go here.
rm "$LINK_OR_DIR"
else
# It's a directory!
# Directory command goes here.
rmdir "$LINK_OR_DIR"
fi
fi
変数を囲むために使用される二重引用符に特に注意してください。この理由は 8jean によって説明されています。 別の答えで.
変数にスペースやその他の異常な文字が含まれている場合、スクリプトが失敗する可能性があります。
他のヒント
バッシュスクリプトでそれらを参照するときは、常に二重引用符で変数をラップすることを忘れないでください。最近の子供たちは、ディレクトリ名にスペースやその他の面白い文字をたくさん入れてもよいという考えを持って成長しています。(スペース!私の時代には、おしゃれなスペースなどありませんでした。;))
ある日、それらの子供の 1 人があなたのスクリプトを実行します。 $DIRECTORY
に設定 "My M0viez"
スクリプトが爆発してしまいます。それは望んでいません。それでこれを使ってください。
if [ -d "$DIRECTORY" ]; then
# Will enter here if $DIRECTORY exists, even if it contains spaces
fi
注意してください -d テストでは驚くべき結果が得られる場合があります。
$ ln -s tmp/ t
$ if [ -d t ]; then rmdir t; fi
rmdir: directory "t": Path component not a directory
ファイルは次の場所にあります:「ディレクトリはいつディレクトリではありませんか?」答え:「それがディレクトリへのシンリンクのとき。」少し徹底的なテスト:
if [ -d t ]; then
if [ -L t ]; then
rm t
else
rmdir t
fi
fi
詳細については、次の Bash マニュアルを参照してください。 Bash の条件式 そしてその [
組み込みコマンド そしてその [[
複合コマンド.
私はそれを見つけました 二重括弧 のバージョン test
ロジック テストをより自然に作成できるようになります。
if [[ -d "${DIRECTORY}" && ! -L "${DIRECTORY}" ]] ; then
echo "It's a bona-fide directory"
fi
短い形式:
[ -d "$DIR" ] && echo "Yes"
ディレクトリが存在するかどうかを確認するには、次のような単純な if 構造を使用できます。
if [ -d directory/path to a directory ] ; then
#Things to do
else #if needed #also: elif [new condition]
# things to do
fi
ネガティブでもできるよ
if [ ! -d directory/path to a directory ] ; then
# things to do when not an existing directory
注記:左中括弧と右中括弧の両側に空のスペースを残すように注意してください。
同じ構文で以下を使用できます。
-e: any kind of archive
-f: file
-h: symbolic link
-r: readable file
-w: writable file
-x: executable file
-s: file size greater than zero
if [ -d "$DIRECTORY" ]; then
# Here if $DIRECTORY exists
fi
使用できます test -d
(見る man test
).
-d file
ファイルが存在し、それがディレクトリである場合は True。
例えば:
test -d "/etc" && echo Exists || echo Does not exist
注記:の test
コマンドは条件式と同じです [
(見る: man [
) なので、シェル スクリプト間で移植可能です。
[
- これはの同義語です。test
組み込みですが、最後の引数はリテラルでなければなりません]
, 、オープニングに合わせて[
.
考えられるオプションや詳細なヘルプについては、以下を確認してください。
help [
help test
man test
またはman [
dir または file が存在するかどうかをテストする簡単なスクリプト:
if [ -d /home/ram/dir ] # for file "if [-f /home/rama/file]" then echo "dir present" else echo "dir not present" fi
ディレクトリが存在するかどうかを確認する簡単なスクリプト:
mkdir tempdir # if you want to check file use touch instead of mkdir ret=$? if [ "$ret" == "0" ] then echo "dir present" else echo "dir not present" fi
上記のスクリプトはディレクトリが存在するかどうかをチェックします
$?
最後のコマンドが成功した場合は「0」を返し、それ以外の場合はゼロ以外の値を返します。仮定するtempdir
その場合はすでに存在しますmkdir tempdir
以下のようなエラーが発生します。mkdir:ディレクトリ「tempdir」を作成できません:ファイルが存在しています
または、まったく役に立たないものについては、次のようにします。
[ -d . ] || echo "No"
非常に実用的なイディオムを次に示します。
(cd $dir) || return # is this a directory,
# and do we have access?
通常はそれを関数でラップします。
can_use_as_dir() {
(cd ${1:?pathname expected}) || return
}
または:
assert_dir_access() {
(cd ${1:?pathname expected}) || exit
}
このアプローチの良い点は、適切なエラー メッセージを考える必要がないことです。
cd
標準の 1 行メッセージが stderr に既に送信されます。また、私が提供できる以上の情報も提供します。を実行することで、 cd
サブシェル内 ( ... )
, 、コマンドは呼び出し元の現在のディレクトリには影響しません。ディレクトリが存在する場合、このサブシェルと関数は何も行われません。
次に渡す引数は、 cd
: ${1:?pathname expected}
. 。これはパラメータ置換のより複雑な形式であり、以下でさらに詳しく説明します。
先生:この関数に渡された文字列が空の場合は、再びサブシェルを終了します。 ( ... )
そして、指定されたエラー メッセージを表示して関数から戻ります。
からの引用 ksh93
マニュアルページ:
${parameter:?word}
もし
parameter
が設定されており、null でない場合は、その値を代入します。それ以外の場合は、印刷しますword
そしてシェルを終了します (対話型でない場合)。もしword
を省略すると、標準メッセージが出力されます。
そして
コロンの場合
:
上記の式から省略されている場合、シェルはパラメーターが設定されているかどうかのみをチェックします。
ここでの表現はシェルのドキュメントに特有のものです。 word
Whitespaceを含む任意の合理的な文字列を参照する場合があります。
この特定のケースでは、標準のエラー メッセージが 1: parameter not set
だけでは不十分なので、ここで期待される値のタイプにズームインします。 pathname
ディレクトリの。
哲学的なメモ:シェルはオブジェクト指向言語ではないため、メッセージは次のようになります。 pathname
, 、 ない directory
. 。このレベルでは、むしろ単純にしておきたいと思います。関数の引数は単なる文字列です。
if [ -d "$Directory" -a -w "$Directory" ]
then
#Statements
fi
上記のコードは、ディレクトリが存在するかどうか、および書き込み可能かどうかをチェックします。
bash プロンプトにこのコードを入力します
if [ -d "$DIRECTORY" ]; then
# if true this block of code will execute
fi
その他の機能を使用して find
サブディレクトリ内のフォルダーの存在を確認します。
found=`find -type d -name "myDirectory"` if [ -n "$found"] then # The variable 'found' contains the full path where "myDirectory" is. # It may contain several lines if there are several folders named "myDirectory". fi
現在のディレクトリ内のパターンに基づいて、1 つまたは複数のフォルダーの存在を確認します。
found=`find -maxdepth 1 -type d -name "my*"` if [ -n "$found"] then # The variable 'found' contains the full path where folders "my*" have been found. fi
両方の組み合わせ。次の例では、現在のディレクトリ内のフォルダーの存在を確認します。
found=`find -maxdepth 1 -type d -name "myDirectory"` if [ -n "$found"] then # The variable 'found' is not empty => "myDirectory"` exists. fi
実際には、確実なアプローチを実現するには、いくつかのツールを使用する必要があります。
DIR_PATH=`readlink -f "${the_stuff_you_test}"` # Get rid of symlinks and get abs path
if [[ -d "${DIR_PATH}" ]] ; Then # now you're testing
echo "It's a dir";
fi
スペースや特殊文字を使用する限り、心配する必要はありません。 "${}"
.
ご了承ください [[]]
ほどポータブルではありません []
, しかし、ほとんどの人は最新バージョンの Bash を使用しているため (結局、ほとんどの人はコマンド ライン :-p を使用することさえないため)、トラブルよりも利点の方が大きくなります。
複数のディレクトリを確認するには、次のコードを使用します。
if [ -d "$DIRECTORY1" ] && [ -d "$DIRECTORY2" ] then
# Things to do
fi
やりたいことだけをやろうと考えたことはありますか? if
飛び上がる前に見るのではなく?
IE で、ディレクトリに入る前にディレクトリの存在を確認したい場合は、次のようにしてみてください。
if pushd /path/you/want/to/enter; then
# commands you want to run in this directory
popd
fi
あなたが与える道なら pushd
が存在する場合は、それを入力すると、次のように終了します。 0
, 、つまり、 then
ステートメントの部分が実行されます。存在しない場合は、何も起こりません (ディレクトリが存在しないという出力を除いて、これはおそらくデバッグに役立つ副作用です)。
これよりも優れているように思えますが、繰り返す必要があります。
if [ -d /path/you/want/to/enter ]; then
pushd /path/you/want/to/enter
# commands you want to run in this directory
popd
fi
同じことが機能します cd
, mv
, rm
, 、など...存在しないファイルに対してこれらを試行すると、エラーで終了し、ファイルが存在しないことを示すメッセージが出力されます。 then
ブロックはスキップされます。存在するファイルに対してこれらを試行すると、コマンドが実行され、次のステータスで終了します。 0
, 、あなたの then
実行するブロック。
ディレクトリが存在するかどうかを確認し、存在しない場合はディレクトリを作成します
[ -d "$DIRECTORY" ] || mkdir $DIRECTORY
[[ -d "$DIR" && ! -L "$DIR" ]] && echo "It's a directory and not a symbolic link"
注意:変数を引用符で囲むことは良い習慣です。
[ -d ~/Desktop/TEMPORAL/ ] && echo "DIRECTORY EXISTS" || echo "DIRECTORY DOES NOT EXIST"
この答えは シェルスクリプトとしてまとめられる
例
$ is_dir ~
YES
$ is_dir /tmp
YES
$ is_dir ~/bin
YES
$ mkdir '/tmp/test me'
$ is_dir '/tmp/test me'
YES
$ is_dir /asdf/asdf
NO
# Example of calling it in another script
DIR=~/mydata
if [ $(is_dir $DIR) == "NO" ]
then
echo "Folder doesnt exist: $DIR";
exit;
fi
is_dir
function show_help()
{
IT=$(CAT <<EOF
usage: DIR
output: YES or NO, depending on whether or not the directory exists.
)
echo "$IT"
exit
}
if [ "$1" == "help" ]
then
show_help
fi
if [ -z "$1" ]
then
show_help
fi
DIR=$1
if [ -d $DIR ]; then
echo "YES";
exit;
fi
echo "NO";
の使用 -e
check はファイルをチェックします。これにはディレクトリも含まれます。
if [ -e ${FILE_PATH_AND_NAME} ]
then
echo "The file or directory exists."
fi
とおり ジョナサン コメント:
ディレクトリを作成したいが、それがまだ存在しない場合、最も簡単な手法は次のとおりです。 mkdir -p
これにより、ディレクトリと、パス上に存在しないディレクトリが作成されます。ディレクトリがすでに存在する場合は失敗しないため、次のようにしてすべてを一度に実行できます。
mkdir -p /some/directory/you/want/to/exist || exit 1
if [ -d "$DIRECTORY" ]; then
# Will enter here if $DIRECTORY exists
fi
これは完全に真実ではありません...そのディレクトリに移動する場合は、そのディレクトリに対する実行権限も必要です。おそらく書き込み権限も必要になるでしょう。
したがって:
if [ -d "$DIRECTORY" ] && [ -x "$DIRECTORY" ] ; then
# ... to go to that directory (even if DIRECTORY is a link)
cd $DIRECTORY
pwd
fi
if [ -d "$DIRECTORY" ] && [ -w "$DIRECTORY" ] ; then
# ... to go to that directory and write something there (even if DIRECTORY is a link)
cd $DIRECTORY
touch foobar
fi
の ls
と組み合わせたコマンド -l
(長いリスト) オプションは、ファイルとディレクトリに関する属性情報を返します。
特に最初の文字は、 ls -l
出力は通常、 d
または -
(ダッシュ)。の場合 d
リストされているものは確かにディレクトリです。
次のコマンドを 1 行で実行すると、指定された条件が満たされているかどうかがわかります。 ISDIR
変数にディレクトリへのパスが含まれるかどうか:
[[ $(ls -ld "$ISDIR" | cut -c1) == 'd' ]] &&
echo "YES, $ISDIR is a directory." ||
echo "Sorry, $ISDIR is not a directory"
実際の使用法:
[claudio@nowhere ~]$ ISDIR="$HOME/Music"
[claudio@nowhere ~]$ ls -ld "$ISDIR"
drwxr-xr-x. 2 claudio claudio 4096 Aug 23 00:02 /home/claudio/Music
[claudio@nowhere ~]$ [[ $(ls -ld "$ISDIR" | cut -c1) == 'd' ]] &&
echo "YES, $ISDIR is a directory." ||
echo "Sorry, $ISDIR is not a directory"
YES, /home/claudio/Music is a directory.
[claudio@nowhere ~]$ touch "empty file.txt"
[claudio@nowhere ~]$ ISDIR="$HOME/empty file.txt"
[claudio@nowhere ~]$ [[ $(ls -ld "$ISDIR" | cut -c1) == 'd' ]] &&
echo "YES, $ISDIR is a directory." ||
echo "Sorry, $ISDIR is not a directoy"
Sorry, /home/claudio/empty file.txt is not a directory
file="foo"
if [[ -e "$file" ]]; then echo "File Exists"; fi;
実際のディレクトリであるかシンボリックリンクであるかに関係なく、ディレクトリが存在するかどうかを確認したい場合は、これを使用します。
ls $DIR
if [ $? != 0 ]; then
echo "Directory $DIR already exists!"
exit 1;
fi
echo "Directory $DIR does not exist..."
説明:「ls」コマンドを実行すると、「ls:」というエラーが発生します。/バツ:ディレクトリまたはシンボリックリンクが存在しない場合は、「そのようなファイルまたはディレクトリはありません」と表示され、また、「$?」で取得できる戻りコードが非 null (通常は「1」) に設定されます。「ls」を呼び出した直後にリターンコードを確認してください。
(1)
[ -d Piyush_Drv1 ] && echo ""Exists"" || echo "Not Exists"
(2)
[ `find . -type d -name Piyush_Drv1 -print | wc -l` -eq 1 ] && echo Exists || echo "Not Exists"
(3)
[[ -d run_dir && ! -L run_dir ]] && echo Exists || echo "Not Exists"
上記のいずれかのアプローチで問題が見つかった場合。
と ls
指示;ディレクトリが存在しない場合 - エラーメッセージが表示される
$ [[ ls -ld SAMPLE_DIR| grep ^d | wc -l
-eq 1]] && echoが存在します||存在しない-ksh:ない:見つかりません [そのようなファイルまたはディレクトリはありません]
素晴らしいソリューションはありますが、適切なディレクトリにいない場合、最終的にはすべてのスクリプトが失敗します。したがって、次のようなコードを作成します。
if [ -d "$LINK_OR_DIR" ]; then
if [ -L "$LINK_OR_DIR" ]; then
# It is a symlink!
# Symbolic link specific commands go here
rm "$LINK_OR_DIR"
else
# It's a directory!
# Directory command goes here
rmdir "$LINK_OR_DIR"
fi
fi
実行時に、たまたまチェックしたサブディレクトリがあるディレクトリにいる場合にのみ、正常に実行されます。
最初の質問は次のように理解しました。ファイル システム内のユーザーの位置に関係なく、ディレクトリが存在するかどうかを確認します。したがって、「find」コマンドを使用すると、うまくいく可能性があります。
dir=" "
echo "Input directory name to search for:"
read dir
find $HOME -name $dir -type d
このソリューションは、ファイル/ディレクトリを検索するときに便利な機能であるワイルドカードを使用できるため、優れています。唯一の問題は、検索されたディレクトリが存在しない場合、「find」コマンドは stdout に何も出力せず (私の好みでは洗練された解決策ではありません)、それでも終了がゼロになることです。たぶん誰かがこれを改善できるでしょう。
以下の検索を使用できます。
find . -type d -name dirname -prune -print