シェルスクリプトにファイルが存在するかどうかを確認する方法


175

特定のファイル、archived_sensor_data.jsonが存在するかどうかを確認し、存在する場合は削除するシェルスクリプトを記述したいと思います。http://www.cyberciti.biz/tips/find-out-if-file-exists-with-conditional-expressions.htmlに続いて、私は以下を試しました:

[-e archived_sensor_data.json] && rm archived_sensor_data.json

ただし、これはエラーをスローします

[-e: command not found

コマンドtest_controllerを使用して結果のスクリプトを実行しようとすると、./test_controllerコードの何が問題になっていますか?



2
角かっこ「[」とオプション「-e」の間に、ファイル名と角かっこ「]」の間に同じように1つ以上の空白を設定する必要があります
Konstantin Yaniv

回答:


349

ブラケットとの間に必要なスペースがありません-e

#!/bin/bash
if [ -e x.txt ]
then
    echo "ok"
else
    echo "nok"
fi

12
私は最後に2つの空白スペースを追加しました[ -e archived_sensor_data.json ] && rm archived_sensor_data.json。スクリプトは現在動作しているようです。
カートピーク

3
これはif [ -e "$1" ](ファイル名入力引数)を使用しても機能します。
エドワード

2
ここでの主な違いは、「シェル」スクリプトではなく「bash」スクリプトを使用しているという事実です。追加した最初の行は#!/ bin / bashだったので、shではなく「bash」を使用するようにマシンに指示していることに注意してください。shがその引数 "-e"を認識しないため
Nick Cuevas

29

ここに使用する別の方法がありlsます:

(ls x.txt && echo yes) || echo no

出力を非表示にしてlsyesまたはnoのみを表示する場合は、リダイレクトstdoutstderr/dev/null次のようにしてください。

(ls x.txt >> /dev/null 2>&1 && echo yes) || echo no

1
このコードは、「ls成功した場合、そのようなファイルが存在し、そうでない場合は存在しない」ことを意味します。ls失敗した場合でも、ファイルが欠落しているとは限りません。その他のエラーの可能性があります。たとえば、rootが所有するディレクトリにファイルを作成しls、通常のユーザーで実行してみます。で失敗しますがPermission denied、これはファイルが存在しないことと同等ではありません。
Tigran、

9

私が推奨するソリューションの背景には、最初の仕事の2週目に、ビルドサーバーの半分を完全に消去した友人の話があります。したがって、基本的なタスクは、ファイルが存在するかどうかを確認することです。存在する場合は削除します。しかし、この川には危険な急流がいくつかあります。

  • すべてがファイルです。

  • スクリプトは、一般的なタスクを解決する場合にのみ本当の力を発揮します

  • 一般的には、変数を使用します

  • 手作業による介入を避けるために、スクリプトではしばしば-f forceを使用します

  • また、-rを再帰的に愛し、タイムリーな方法で作成、コピー、破棄するようにしてください。

次のシナリオを検討してください。

削除したいファイルがあります:filesexists.json

このファイル名は変数に保存されます

<host>:~/Documents/thisfolderexists filevariable="filesexists.json"

物事を本当に柔軟にするために、パス変数も使用します

<host>:~/Documents/thisfolderexists pathtofile=".."

<host>:~/Documents/thisfolderexists ls $pathtofile

filesexists.json  history20170728  SE-Data-API.pem  thisfolderexists

それで、-eそれが想定されていることを行うかどうかを見てみましょう。ファイルは存在しますか?

<host>:~/Documents/thisfolderexists [ -e $pathtofile/$filevariable ]; echo $?

0

します。マジック。

ただし、ファイル変数が誤ってnuffinと評価された場合はどうなりますか?

<host>:~/Documents/thisfolderexists filevariable=""

<host>:~/Documents/thisfolderexists [ -e $pathtofile/$filevariable ]; echo $?

0

何?エラーで戻るはずです...そして、これがそのフォルダ全体が誤って削除された話の始まりです

別の方法として、「ファイル」であると私たちが理解していることを具体的にテストすることもできます

<host>:~/Documents/thisfolderexists filevariable="filesexists.json"

<host>:~/Documents/thisfolderexists test -f $pathtofile/$filevariable; echo $?

0

したがって、ファイルは存在します...

<host>:~/Documents/thisfolderexists filevariable=""

<host>:~/Documents/thisfolderexists test -f $pathtofile/$filevariable; echo $?

1

したがって、これはファイルではなく、おそらくディレクトリ全体を削除したくない

man test 次のように言っています:

-b FILE

       FILE exists and is block special

-c FILE

       FILE exists and is character special

-d FILE

       FILE exists and is a directory

-e FILE

       FILE exists

-f FILE

       FILE exists and is a regular file

...

-h FILE

       FILE exists and is a symbolic link (same as -L)

4

内部的には、rmコマンドはファイルの存在をテストする必要がある
ので、なぜ別のテストを追加するのですか?ちょうど発行

rm filename

それがあったかどうかにかかわらず、それはその後消えてしまいます。
rm -fを使用すると、存在しないファイルに関するメッセージは表示されません。

ファイルが存在しない場合に何らかのアクションを実行する必要がある場合は、自分でテストする必要があります。あなたのサンプルコードに基づいて、これはこの例では当てはまりません。


1
これは、実際にはrmコマンドのかなり有効な回答です。他のコマンドについては、-eを使用してテストすることをお勧めします。
warhansen

それは質問が尋ねるものではないことを除いて。
クレヨン

1
「...と(もしそうなら)...削除する」の部分を含む質問全体を読んだ場合、それは質問が尋ねるものです。
TG

1

NFSを使用している場合は、NFSがダウンした場合にタイムアウトを追加できるため、「テスト」がより良いソリューションです。

time timeout 3 test -f 
/nfs/my_nfs_is_currently_down
real    0m3.004s <<== timeout is taken into account
user    0m0.001s
sys     0m0.004s
echo $?
124   <= 124 means the timeout has been reached

「[-e my_file]」構文は、NFSが再び機能するまでフリーズします。

if [ -e /nfs/my_nfs_is_currently_down ]; then echo "ok" else echo "ko" ; fi

<no answer from the system, my session is "frozen">

test[同義です。あなたは使用することができるtimeout[同様に、そしてtestまた、NFSがハングした場合にフリーズします。
他の男、
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.