find: ファイルが指定されていない場合は何もしない

find: ファイルが指定されていない場合は何もしない

いくつかのファイル名でuse を呼び出したいですfind

find $(do_something to find filenames) -print0 | xargs -r0 ls -ld

何も返さない場合は、これは機能しません$(do_something to find filenames)。find コマンドは再帰検索を開始します。

引数として明示的なファイル名/ディレクトリ名を取得しない場合に find に何もしないように指示する方法はありますか?

答え1

の場合zsh、私は次のようにします:

files=($(do_something to find filenames))
(($#files)) && find $files ...

tcsh

set files=(`do_something to find filenames`)
if ($#files) find $files:q ...

bash、または、mkshksh93

set -f; files=($(do_something to find filenames))
((${#files[@]})) && find "${files[@]}" ...

POSIX 的には:

set -f; set -- $(do_something to find filenames)
[ "$#" -gt 0 ] && find "$@" ...

(bash やその他の POSIX シェルでは、$(...)分割 ($IFSデフォルトではスペース、タブ、改行) しますが、結果の単語に対してグロブも実行します。これはここでは必要ないと予想されるため、 をset -f使用します。他のシェル ((t)csh、zsh、fish、rc、es など) にはこの問題はありません。)

答え2

次のようにしてみてはどうでしょうか:

paths=$(do_something to find filenames)
if [ "$paths" ]; then
    find "$paths" ...
fi

これはfind実装とは独立して動作します。

find "$paths"パス名が複数あると問題が発生することに注意してください。パス名にスペースが含まれていない場合は、 を使用できます。find $pathsそれ以外の場合は、次の関数が代わりに機能します。

dofind() {
    set -f
    set -- $(do_something to find filenames)
    if [ $# -gt 0 ]; then
        find "$@" ...
    fi
    set +f
}

ファイルのグロビングを無効にし、set --シェルの引数ベクトルを設定するために使用します。これは、どの POSIX シェルでも機能します。

答え3

find存在しない追加のディレクトリを開始元として指定できます。

find " " $(do_something to find filenames) -print0 | xargs -r0 ls -ld

これを整理するには、findのエラー出力を削除します。

find " " $(do_something to find filenames) -print0 2>/dev/null | xargs -r0 ls -ld

(ただし、別のエラーが発生しても気付かないでしょう...)。

ファイル名を出力する場合do_something to find filenamesfindは について文句を言います" "が、コマンドラインの残りの部分は処理されます。ファイル名が出力されない場合は、findは について再度文句を言います" "が、デフォルトの は追加されません.

答え4

(およびほとんどの非Bourne派生シェル)ではzsh、(または全てシェルによって異なります)グロブ展開されない場合、コマンドは中止されます。

$(do_something to find filenames)はグロブではありませんが、次のようにグロブ修飾子を追加することでグロブにすることができますzsh

 find $(do_something to find filenames)(#q) -print0...

上記では、(#q)(空の glob 修飾子なので、それ以外は何も行いません)が の出力を分割した結果の最後の単語に追加されるため、do_something to find filenamesそのコマンドが出力を生成しない場合(または空白の場合)だけでなく、最後の単語(最後の単語のみ)が既存のパスに解決されない場合も、コマンドは中止されます。次のようにして、分割の結果の単語すべてに適用できます(つまり、それらの単語のいずれかが既存のファイルに解決されない場合、コマンドは中止されます)。

 find ${^$(do_something to find filenames)}(#q) -print0...

関連情報