Bashシェルスクリプト内で、ディレクトリが存在するかどうかを確認するために使用できるコマンドは何ですか?
35 に答える
ディレクトリがシェルスクリプトに存在するかどうかを確認するには、次を使用できます。
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
ただし、Jon Ericsonが指摘しているように、ディレクトリへのシンボリック リンクもこのチェックに合格することを考慮しないと、後続のコマンドが意図したとおりに機能しない可能性があります。たとえば、これを実行します:
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 によって説明されています。
変数にスペースやその他の特殊な文字が含まれていると、スクリプトが失敗する可能性があります。
Bash スクリプトで変数を参照するときは、常に変数を二重引用符で囲むことを忘れないでください。最近の子供たちは、ディレクトリ名にスペースやその他の面白い文字をたくさん入れることができるという考えを持って成長しています。(スペース! 私の時代には、派手なスペースはありませんでした! ;))
ある日、それらの子供の 1 人がスクリプトを$DIRECTORY
set で実行し"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
短縮形:
# if $DIR is a directory, then print yes
[ -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
を使用できます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 [
または完全に役に立たない何かのために:
[ -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行メッセージが表示されます。また、私が提供できるよりも多くの情報を提供します。cd
サブシェル内で実行することにより( ... )
、コマンドは呼び出し元の現在のディレクトリに影響を与えません。ディレクトリが存在する場合、このサブシェルと関数は何もしません。
cd
次は:に渡す引数です${1:?pathname expected}
。これは、以下で詳しく説明する、より精巧な形式のパラメーター置換です。
Tl;dr: この関数に渡された文字列が空の場合、再びサブシェル( ... )
を終了し、指定されたエラー メッセージとともに関数から戻ります。
ksh93
マニュアルページから引用:
${parameter:?word}
が設定されていて null でない場合
parameter
は、その値を置き換えます。それ以外の場合は、出力word
してシェルを終了します (対話的でない場合)。を省略するword
と、標準のメッセージが出力されます。
と
上記の式からコロン
:
を省略すると、シェルはパラメータが設定されているかどうかのみをチェックします。
ここでの言い回しは、シェルのドキュメントに特有のものであり、word
空白を含む適切な文字列を指す場合があります。
この特定のケースでは、標準のエラー メッセージ1: parameter not set
では不十分であることがわかっているので、ここで期待される値のタイプ、つまりpathname
ディレクトリのタイプを拡大します。
哲学的なメモ:
シェルはオブジェクト指向言語ではないため、メッセージにはpathname
ではなくと表示されますdirectory
。このレベルでは、むしろシンプルに保ちたいと思います。関数への引数は単なる文字列です。
if [ -d "$Directory" -a -w "$Directory" ]
then
#Statements
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
Bash プロンプトで次のコードを入力します。
if [ -d "$DIRECTORY" ]; then
# If true this block of code will execute
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
飛躍する前に見るのではなく、やりたいことを何でもやろうと考えたことはありますか?
つまり、ディレクトリに入る前にディレクトリの存在を確認したい場合は、次のようにしてみてください。
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 "$DIR" && ! -L "$DIR" ]] && echo "It's a directory and not a symbolic link"
注意: 変数をクォートすることは良い習慣です。
説明:
-d
: ディレクトリかどうかを確認します-L
: シンボリック リンクかどうかを確認します
複数のディレクトリを確認するには、次のコードを使用します。
if [ -d "$DIRECTORY1" ] && [ -d "$DIRECTORY2" ] then
# Things to do
fi
ディレクトリが存在するかどうかを確認し、存在しない場合は作成します。
[ -d "$DIRECTORY" ] || mkdir $DIRECTORY
この回答はシェルスクリプトとしてまとめられています
例
$ 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";
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
ジョナサンのコメントによると:
ディレクトリを作成したいが、それがまだ存在しない場合、最も簡単な方法はmkdir -p
、ディレクトリを作成する方法を使用することです (パス上に存在しないディレクトリを作成し、ディレクトリが既に存在する場合は失敗しないため、すべてを実行できます)。一度に:
mkdir -p /some/directory/you/want/to/exist || exit 1
このls
コマンドを (長いリスト) オプションと組み合わせて使用すると-l
、ファイルとディレクトリに関する属性情報が返されます。
特に、ls -l
出力の最初の文字は通常 ad
または a -
(ダッシュ) です。の場合、d
リストされているのは確かにディレクトリです。
ISDIR
次のコマンドを 1 行で実行すると、指定された変数にディレクトリへのパスが含まれているかどうかがわかります。
[[ $(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;
以下find
を使用できます。
find . -type d -name dirname -prune -print
実際のディレクトリかシンボリックリンクかに関係なく、ディレクトリが存在するかどうかを確認する場合は、次を使用します。
ls $DIR
if [ $? != 0 ]; then
echo "Directory $DIR already exists!"
exit 1;
fi
echo "Directory $DIR does not exist..."
説明: ディレクトリまたはシンボリックリンクが存在しない場合、「ls」コマンドはエラー「ls: /x: No such file or directory」を返し、「$?」で取得できる戻りコードを非に設定します。 -null (通常は「1」)。「ls」を呼び出した直後に、必ずリターン コードを確認してください。