シェルスクリプト内にディレクトリが存在するかどうかを確認する

StackOverflow https://stackoverflow.com/questions/59838

  •  09-06-2019
  •  | 
  •  

質問

シェルスクリプト内でディレクトリが存在するかどうかを確認するにはどのようなコマンドを使用できますか?

役に立ちましたか?

解決

シェル スクリプトにディレクトリが存在するかどうかを確認するには、次のコマンドを使用できます。

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 [
  1. dir または file が存在するかどうかをテストする簡単なスクリプト:

    if [ -d /home/ram/dir ]   # for file "if [-f /home/rama/file]" 
    then 
        echo "dir present"
    else
        echo "dir not present"
    fi
    
  2. ディレクトリが存在するかどうかを確認する簡単なスクリプト:

    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
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top