パスを一覧表示せずにファイル名を一覧表示するためにfindコマンドを使用する方法は?

パスを一覧表示せずにファイル名を一覧表示するためにfindコマンドを使用する方法は?

オンラインでいくつかの答えを確認しましたが、コマンドにパラメータがあると機能しません-name(おそらく私が何か間違っているかどうかはわかりません)。私が望むのは、ファイル名(ディレクトリ/パスではない)だけをリストすることです。より複雑にするには、ファイル名は同じですが拡張子が異なるため、およびを-name使用して結果をフィルタリングする必要があります。-o質問は私の提案です。または-printf時にはbasename正しく機能しないことがあります-name *.txt -o name *.pdf。この問題を解決する他の方法はありますか?

私のファイルの例:

/dir1/dir2/dir3/dir4/
                    /file1.txt
                    /file1.pdf
                    /file1.ods ...etc.

リストごとにリストされている1つ以上の種類のファイルにのみ興味があります(-name

たった1つのコマンドで実行できますか?findまたは、手順2で実行する必要があります(結果を一時ファイルに保存してから一時ファイルからディレクトリをフィルタリング/削除する)。私が達成したいことの結果は、各行にファイル名を持つテキストファイルです。

file1.txt
file1.pdf
file1.ods
file2.txt
file2.pdf
etc.

私が使用するコマンドは

find /dir1/dir2/dir3/dir4/ -type f -name '*.txt' -o -name '*.pdf' -o -name '*.ods' -printf "%f\n"

私はGNU Findを使用しています。

修正する

\(...\)αГsнιιが私に思い出させてくれるようにを入れなければならないことが判明しました。

答え1

論理ORパターンで複数の式を使用する場合は、その-o式をすべて囲む必要があります\( ... \)。それ以外の場合、最後の式の結果は常に尊重され、-printf '%f\n'すべての先行ディレクトリが削除されたファイル名のみを印刷するために使用されます。

find . -type f \( -name '*.pdf' -o -name '*.txt' \) -printf '%f\n'

バラよりman find下にオペレーター次のセクションに関して( expr ):

オペレーター
...

(expr)
優先順位を強制します。括弧はシェルに特別なので、通常は引用符で囲む必要があります。

したがって\( ... \)、または'(' ... ')'(括弧の前と後の空白が重要です)を使用してエスケープできます。

答え2

-nameすでに述べたように、テストは括弧内にグループ化する必要があります。これらの括弧は、\( ... \)たとえば'(' ... ')'シェルから保護するためにエスケープまたは引用する必要があります(そうでない場合はサブシェルを指定します)。

標準を使用findし、ファイル名のサフィックス処理を少し簡単にします。

set -- txt pdf ods

for suffix do
    set -- "$@" -o -name "*.$suffix"
    shift
done
shift

find /dir1/dir2/dir3/dir4 \( "$@" \) -type f -exec basename {} \;

まず、位置引数を表示するファイル名のサフィックスのリストに設定し(またはこれがスクリプトの場合はコマンドラインから取得します)、-nameテストのORリストを設定します。その後、コマンドラインで使用してくださいfind

その後、コマンドfind自体はbasename見つかった名前ごとにユーティリティを呼び出します。

あるいは、パラメータ置換を使用して、各パス名のファイル名部分を除くすべてを削除できます。ただし、これを行うには、パス名をインラインsh -cスクリプトに渡す必要があります。

# [...] as before [...]

find /dir1/dir2/dir3/dir4 \( "$@" \) -type f -exec sh -c '
    for pathname do
        printf "%s\n" "${pathname##*/}"
    done' sh {} +

basename少なくとも処理するファイル名が多い場合は、使用されているバリアントよりも速く実行されると期待します。ただし、GNU用のcoreutilsを使用すると、次のようにbasename使用できます。-a--multiple

find /dir1/dir2/dir3/dir4 \( "$@" \) -type f -exec basename -a {} +

basenameこれはできるだけ少ない回数で呼び出されます。ただし、coreutilsがインストールされている場合は、GNUを使用して同じ操作を実行するためにfind使用できるfindutilsをインストールすることもできます。-printf '%f\n'

関連情報