フォルダがあることを確認し、フォルダがある場合は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
テストは失敗します。 -z
1つのオペランドのみが必要なため、複数のディレクトリがある場合、テストコマンドは失敗します。
したがって、否定的なテストに合格します。
- ディレクトリが1つしかない場合、
例:
$ 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
[[ ... ]]
.