execが期待どおりに機能しない場合

execが期待どおりに機能しない場合

フォルダがあることを確認し、フォルダがある場合は1つの操作を実行し、ない場合は別の作業を実行する必要があります。これを行うにはfindを使用しますが、正しい方法が見つかりません。

find /path/to/destination -maxdepth 1 -type d -name "dir*" -exec bash -c '[[ $1 ]] && echo ok || echo "not ok"' _ {} \;

しかし、bash部分の部分は、実装するためにより新しいです。提案はありますか?

答え1

これは、前の条件(and)と一致するファイルに対してのみ実行され、ファイル-execごとに1回実行されます。-name 'dir*'-type d

ここでは、次のことができますzsh

dirs=(/path/to/destination/dir*(N/))
if (($#dirs)); then
  echo Found these dirs:
  printf ' - %s\n' $dirs
else
  echo >&2 No dir found
fi

または、bashバージョン4.4以降とfind互換性のあるGNUを使用している場合(-maxdepth使用時にすでにGNU拡張を使用している必要があります):

readarray -td '' dirs < <(
  find /path/to/destination -maxdepth 1 -type d -name "dir*" -print0)

if ((${#dirs[@]})); then
  echo Found these dirs:
  printf ' - %s\n' "${dirs[@]}"
else
  echo >&2 No dir found
fi

答え2

その名前パターンと一致するディレクトリがあるかどうかを確認するには、findそのディレクトリのダミー出力を印刷し、出力が空であることを確認できます。たとえば、

if [[ "$(find -type d -name "dir*" -printf .)" ]] ; then
    echo "some matching directory exists"
else 
    echo "no matching directory exists"
fi

find渡すこともできます。コマンドが出力を生成しない場合、問題はありません。-exec bash -c '...' _ {} \;-printf

開始されたコマンドの出力をキャプチャし、それを仮想出力から切り離す必要がある場合、find状況はさらに悪化します。一時ファイルまたはリダイレクトトリックが必要です。これはsomecmd、一致するすべてのディレクトリで実行する必要があり、find実行出力をsomecmdスクリプトstdoutに送信し、一致するものがあるかどうかを知らせる必要があります。

exec 3>&1
any=$(find -type d -name "dir*" -printf . -exec bash -c 'somecmd "$1" >&3' _ {} \; )
if [[ "$any" ]] ; then
    echo "matching directories were processed"
else 
    echo "no matching directory exists"
fi
exec 3>&-

もちろん命令が出たらfind いつも出力を生成し、ダミー出力は必要ありません。印刷物をキャプチャして空であるfindことを確認してください。

答え3

醜いですが、bashでは次のようになります。

(shopt -s nullglob; if ! [ -z /path/to/destination/dir*/ ] 2>&-; then  echo ok; else echo not ok; fi)

有効にすると、nullglob次に/path/to/destination/dir*/展開されます。

  • 一致するディレクトリがない場合、何もしません。この場合、テストは-z成功し、否定的なテストは失敗します。
  • または、一致するすべてのディレクトリのリストです。この場合:

    • ディレクトリが1つしかない場合、-zテストは失敗します。
    • -z1つのオペランドのみが必要なため、複数のディレクトリがある場合、テストコマンドは失敗します。

    したがって、否定的なテストに合格します。

例:

$ if ! [ -z /a* ] 2>&-; then  echo ok; else echo not ok; fi
not ok
$ if ! [ -z /b* ] 2>&-; then  echo ok; else echo not ok; fi # multiple: /bin /boot 
ok
$ if ! [ -z /h* ] 2>&-; then  echo ok; else echo not ok; fi # single: /home
ok

[[ ... ]].

関連情報