コマンドが空の文字列を出力するかどうかをテストするにはどうすればよいですか?
ifne
このためのユーティリティがあります。joeyh.name/code/moreutils
コマンドが空の文字列を出力するかどうかをテストするにはどうすればよいですか?
ifne
このためのユーティリティがあります。joeyh.name/code/moreutils
回答:
以前は、ディレクトリにファイルがあるかどうかを確認する方法についての質問がありました。次のコードはそれを実現しますが、より良いソリューションについてはrspの回答を参照してください。
コマンドは値を返さず、出力します。この出力は、コマンド置換を使用してキャプチャできます。例えば$(ls -A)
。次のように、Bashで空でない文字列をテストできます。
if [[ $(ls -A) ]]; then
echo "there are files"
else
echo "no files found"
fi
シンボリックの現在の()および親()のディレクトリエントリが省略されているため、-A
ではなくを使用したことに注意してください。-a
.
..
注:コメントで指摘されているように、コマンド置換では末尾の改行はキャプチャされません。したがって、コマンドが改行のみを出力する場合、置換は何もキャプチャせず、テストはfalseを返します。非常にまれですが、上記の例ではこれが可能です。単一の改行が有効なファイル名だからです!この回答の詳細情報。
コマンドが正常に完了したことを確認する場合$?
は、最後のコマンドの終了コード(成功の場合はゼロ、失敗の場合はゼロ以外)を含むを検査できます。例えば:
files=$(ls -A)
if [[ $? != 0 ]]; then
echo "Command failed."
elif [[ $files ]]; then
echo "Files found."
else
echo "No files found."
fi
詳細はこちら。
if [[ $(ls -A | head -c1 | wc -c) -ne 0 ]]; then ...; fi
私のオリジナルを改善する提案をしてくれたnetjに感謝します。if [[ $(ls -A | wc -c) -ne 0 ]]; then ...; fi
これは古い質問ですが、いくつかの改善または少なくともいくつかの説明を必要とする少なくとも2つのことがわかります。
私が目にする最初の問題は、ここで提供される例のほとんどが単に機能しないことです。ls -al
およびls -Al
コマンドを使用します-どちらも空のディレクトリに空でない文字列を出力します。これらの例は、ファイルがない場合でも常にファイルがあることを報告します。
そのため、次のように使用する必要がありますls -A
- -l
とにかく、出力があるかどうかをテストしたいだけなのに、「長いリスト形式を使用する」という意味のスイッチを使用したいのはなぜですか。
したがって、ここでの答えのほとんどは単に正しくありません。
2番目の問題は、一部の回答は問題なく機能するが(使用しないls -al
かls -Al
、ls -A
代わりに)、すべて次のようなことを行うことです。
私が代わりに行うことをお勧めします:
using head -c1
たとえば、次の代わりに:
if [[ $(ls -A) ]]
私は使うだろう:
if [[ $(ls -A | wc -c) -ne 0 ]]
# or:
if [[ $(ls -A | head -c1 | wc -c) -ne 0 ]]
の代わりに:
if [ -z "$(ls -lA)" ]
私は使うだろう:
if [ $(ls -lA | wc -c) -eq 0 ]
# or:
if [ $(ls -lA | head -c1 | wc -c) -eq 0 ]
等々。
小さな出力の場合は問題にならないかもしれませんが、大きな出力の場合は差が大きくなる可能性があります。
$ time [ -z "$(seq 1 10000000)" ]
real 0m2.703s
user 0m2.485s
sys 0m0.347s
それと比較してください:
$ time [ $(seq 1 10000000 | wc -c) -eq 0 ]
real 0m0.128s
user 0m0.081s
sys 0m0.105s
そしてさらに良い:
$ time [ $(seq 1 10000000 | head -c1 | wc -c) -eq 0 ]
real 0m0.004s
user 0m0.000s
sys 0m0.007s
Will Vousdenの回答の更新例:
if [[ $(ls -A | wc -c) -ne 0 ]]; then
echo "there are files"
else
echo "no files found"
fi
netjによる提案の後に再度更新:
if [[ $(ls -A | head -c1 | wc -c) -ne 0 ]]; then
echo "there are files"
else
echo "no files found"
fi
jakeonfireによる追加の更新:
grep
一致しない場合は失敗して終了します。これを利用して、構文を少し単純化できます。
if ls -A | head -c1 | grep -E '.'; then
echo "there are files"
fi
if ! ls -A | head -c1 | grep -E '.'; then
echo "no files found"
fi
テストしているコマンドが空の文字列として扱いたい空白を出力する可能性がある場合は、次の代わりに:
| wc -c
あなたは使うことができます:
| tr -d ' \n\r\t ' | wc -c
またはhead -c1
:
| tr -d ' \n\r\t ' | head -c1 | wc -c
またはそのようなもの。
まず、動作するコマンドを使用します。
第2に、RAMへの不要な保存と、潜在的に巨大なデータの処理を避けます。
答えは、出力が常に小さいことを指定していなかったため、大きな出力の可能性も考慮する必要があります。
[[ $(... | head -c | wc -c) -gt 0 ]]
または、コマンドの出力全体を消費する必要[[ -n $(... | head -c1) ]]
があるため、より優れていwc -c
ます。
if [ -z "$(ls -lA)" ]; then
echo "no files found"
else
echo "There are files"
fi
これによりコマンドが実行され、返された出力(文字列)の長さがゼロかどうかが確認されます。他のフラグについては、「テスト」のマニュアルページを確認してください。
チェックされる引数の前後に ""を使用します。それ以外の場合、空の結果は、指定された(チェックする)2番目の引数がないため構文エラーになります!
注:これはls -la
常に戻るため.
、..
それを使用しても機能しません。lsのマニュアルページを参照してください。さらに、これは便利で簡単に思えるかもしれませんが、簡単に壊れてしまうと思います。結果に応じて0または1を返す小さなスクリプト/アプリケーションを書くと、はるかに信頼性が高くなります。
$(
ので、バッククォートの代わりに使用することをお$(
エレガントでbashのバージョンに依存しないソリューションが必要な場合(実際には他の最新のシェルで動作するはずです)と、ワンライナーを使用して迅速なタスクを行うのが好きな人のために。さあ行こう!
ls | grep . && echo 'files found' || echo 'files not found'
(言及されたコメントの1つとして注意してください、ls -al
そして実際、ちょうど-l
そして-a
すべてが何かを返すので、私の答えでは私は単純なls
grep -q ^
代わりに使用すると、改行文字も一致し、grepは標準出力に何も出力しません。さらに、入力ストリームが終了するのを待つのではなく、入力を受信するとすぐに終了します。
ls -A
ますが、ドットファイル(またはディレクトリ)を含めたい場合は
-z string
True if the length of string is zero.
-n string
string
True if the length of string is non-zero.
省略形を使用できます。
if [[ $(ls -A) ]]; then
echo "there are files"
else
echo "no files found"
fi
string
はの同義語であることがわかります-n string
。
Jon Linがコメントしたように、ls -al
常に出力されます(.
および..
)。ls -Al
これらの2つのディレクトリは避けたいものです。
たとえば、コマンドの出力をシェル変数に入れることができます。
v=$(ls -Al)
古い、ネストできない、表記は
v=`ls -Al`
しかし、私はネスト可能な表記を好み$(
ます...)
その変数が空でないかどうかをテストできます
if [ -n "$v" ]; then
echo there are files
else
echo no files
fi
そして、両方を組み合わせることができます if [ -n "$(ls -Al)" ]; then
ls -al
コマンドの出力が必要だと思うので、bashでは次のようになります。
LS=`ls -la`
if [ -n "$LS" ]; then
echo "there are files"
else
echo "no files found"
fi
ls
。コマンドが実行されることはありません。変数 の展開がLS
空でないかどうかを確認するだけです。
-a
スイッチは、(そこにあるファイルであるかどうか、すなわち、それはコンテンツを返します)は常に暗黙のがあるので、何の内容を返すことはありません.
し、..
ディレクトリの存在。
これまでの回答はすべて、空でない文字列を終了して出力するコマンドを扱っています。
ほとんどは次の意味で壊れています:
yes
)。これらの問題をすべて修正し、次の質問に効率的に回答するには、
コマンドが空の文字列を出力するかどうかをテストするにはどうすればよいですか?
あなたは使うことができます:
if read -n1 -d '' < <(command_here); then
echo "Command outputs something"
else
echo "Command doesn't output anything"
fi
read
の-t
オプションを使用して、特定の時間内にコマンドが空でない文字列を出力するかどうかをテストするために、タイムアウトを追加することもできます。たとえば、2.5秒のタイムアウトの場合:
if read -t2.5 -n1 -d '' < <(command_here); then
echo "Command outputs something"
else
echo "Command doesn't output anything"
fi
リマーク。コマンドが空でない文字列を出力するかどうかを判断する必要があると思われる場合は、XYの問題が発生している可能性があります。
seq 1 10000000
、seq 1 20
、およびprintf""
)。この読み取りアプローチが成功しなかった唯一のマッチアップ-z "$(command)"
は、空の入力に対するアプローチでした。それでも、約10〜15%しか失われません。周りでも壊れそうですseq 1 10
。いずれにせよ、入力サイズが大きく-z "$(command)"
なるにつれてアプローチが非常に遅くなるため、可変サイズの入力には使用しないでください。
次に、いくつかのコマンドのstd-outおよびstd-errを一時ファイルに書き込み、そのファイルが空かどうかを確認する別の方法を示します。このアプローチの利点は、両方の出力をキャプチャし、サブシェルやパイプを使用しないことです。これらの後者の側面は、bash出口処理のトラップを妨害する可能性があるため重要です(例:ここ)
tmpfile=$(mktemp)
some-command &> "$tmpfile"
if [[ $? != 0 ]]; then
echo "Command failed"
elif [[ -s "$tmpfile" ]]; then
echo "Command generated output"
else
echo "Command has no output"
fi
rm -f "$tmpfile"
空でない場合は、出力を保存して別のコマンドに渡すこともできます。もしそうなら、あなたは次のようなものを使うことができます
list=`grep -l "MY_DESIRED_STRING" *.log `
if [ $? -eq 0 ]
then
/bin/rm $list
fi
このように、rm
リストが空の場合、コマンドはハングしません。