ロケート検索でディレクトリを除外する


12

locateファイルシステム内のパスを見つける検索。
多くの場合、ファイルのみ、またはディレクトリのみに関心があることをアプリオリに知っています。
「検索」検索は多くの場合、多くの結果を返します。出力を短縮するのに役立つため、結果にタイプの1つのみを含めると便利です。

しかし、ファイルまたはディレクトリのいずれかを除外するより興味深い議論があります。結果パスのリストは、理論だけでなくあいまいになる可能性があるためです。

以下の例は実際のケースであり、珍しいものではありません。

$ locate --regex --basename "xfce4-keyboard-overlay$"
/usr/local/bin/xfce4-keyboard-overlay
/usr/local/share/xfce4-keyboard-overlay

OK、私たちは何かを見つけました!しかし...ファイル、またはディレクトリ?

$ file /usr/local/bin/xfce4-keyboard-overlay 
/usr/local/bin/xfce4-keyboard-overlay:   bash script

それはファイルです...

$ file /usr/local/share/xfce4-keyboard-overlay
/usr/local/share/xfce4-keyboard-overlay: directory

2番目はそうではありません。

このあいまいさにより、パスの長いリストが読みにくくなるため、たとえば、のコマンドラインオプションを使用して、ディレクトリを除外することは本当に便利ですlocate

このようなものはありますか?ディレクトリのフィルターがロケートとは別の場合でも?

少なくとも、スクリプトを使用して、チェックするすべてのファイル名を繰り返すことができます-これは遅いかもしれません。

回答:


3

zsh

print -rl ${(0)^"$(locate -0 ...)"}(N.)

(0)は、(使用するようにlocate -0)NUL文字で分割するパラメーター拡張フラグです(ps:\0:)

を使用して^(N.)配列の最後に追加する代わりに、各要素に追加します。

(N.)は、.通常のファイルのみに一致するグロブ修飾子です。N一致しない場合は要素を削除します(存在しないか、通常のファイルではないか、チェックできません)。また、^/代わりに.を使用して、通常のファイルだけでなく、ディレクトリ以外と一致させることもできます。

print -rl各引数を個別の行にで出力します。

任意のzshglob修飾子を使用できますが、ここではファイルごとに1つのglobを展開しているため、並べ替えるファイルは1つしかないため、順序付けは効果がありません。

(で報告された最後のファイルlocateが改行文字で終わる場合は失敗する可能性があることに注意してください(すべてのシェルにコマンド置換の誤機能が存在します))。


3

これは他の回答と同じくらい洗練されていませんが、非効率的かもしれません。

locate --regex --basename "xfce4-keyboard-overlay$" | 
        while IFS= read -r f; do [ -f "$f" ] && printf "%s\n" "$f"; done

(読みやすくするために2行に分けています)。上記は、スペースを含む名前を処理します。IFS=名を処理するために必要であるように思わ末尾もちろん、スペース、そして-rあなたはバックスラッシュを処理することができます。

locate改行を含むパス名が存在する場合、「何かにパイプしよう」アプローチは失敗する運命にあるかもしれません。


詳細についてはIFS、読みsh(1)またはbash(1) (次のように入力してman shか、man bash* nixのシステムに、および/またはそれを読んで、ここでここではここでは、および/またはここに)。次に、IFSBash について理解する Stack Exchange でIFSを使用て行ごと読みます(5票以上の回答に焦点を当てます)。まだ十分でない場合は、GregのWiki およびIFS検索結果でIFSを確認してくださいBash Hackers Wikiにあります(Stack Exchangeにはありません)。


whileステートメントの後に「IFS =」が何をするかについての情報を追加できますか?
ロバート

私はそうしました。
G-Manによる「Reinstate Monica」

多くのエコー実装では、バックスラッシュが依然として問題になります。任意のデータに使用する必要がありますprintf
ステファンシャゼラス

ここで提案されているようにlocate、「-null」パラメーターを使用して追加することにより、改行の問題を解決できる可能性がありreadますtransnum.blogspot.ie/2008/11/…–
ロバート

@StéphaneChazelas:良い点。修繕。
G-マンは「元に戻すモニカ言う

2
locate --null --regex --basename "xfce4-keyboard-overlay$" |
  xargs -r0 sh -c 'find "$@" -prune ! -type d' sh

実際には、見た目よりもさらに汚れています...しかし良いインスピレーション。擬似コードのふりをしてみましょう、それは役に立ちます:)
Volker Siegel

1
@Volker:それは悪いことに同意します:あなたの例では、それと/usr/local/share/xfce4-keyboard-overlay そのすべてのサブディレクトリがリストされます。ヘルプ-maxdepth 0を追加します。
G-Manは「Reinstate Monica」と言います

さらに良くなります...:D locate --regex --basename "xfce4-keyboard-overlay$" | xargs -I % sh -c "test -d % && echo %"
FloHimself

1
xargswith findを使用するのは良いアイデアでしたが、堅牢にするために編集しました。気にしないでください。
ステファンシャゼル

1

xargs 指定した場合、各行に対してコマンドを繰り返します -L 1または-iパラメータます。

こちらをご覧ください

$ locate --regex --basename "xfce4-keyboard-overlay$" | xargs -i bash -c '(test -d "{}" && echo "{}")'

確かに、ファイルごとに新しいシェルが起動されますが、素晴らしくコンパクトであるという利点があります。

編集:私はそれが各ファイルの新しいシェルを蹴っていたので、その答えにはあまり満足していませんでした。これには2つのプロセスのみが必要です。

$ locate --regex --basename "xfce4-keyboard-overlay$" | xargs -i echo 'test -d "{}" && echo "{}"' | bash

もちろん、インタープリターのキックを完全に回避できればいいのですが、xargsコマンドをチェーンする能力は大げさなようです。


3
その1つはちょうど私のマシンをリブートしました(というファイルが/home/evil/$(reboot)/xfce4-keyboard-overlayあり、私は愚かにそれを実行しましたroot)。
ステファンシャゼル

2
@StéphaneChazelas+1をルートとして「インターネットからランダムコーデック」を実行する勇気のために+1;)(scnr)
Volker Siegel

0

私の2セント:

while IFS= read i; \
do \
  if [ -f "$i" ]; \
  then \
    echo "$i"; \
  fi; \
done < <(locate --regex --basename "xfce4-keyboard-overlay$")

これは、G-Manがプロセス置換と組み合わせた方法とほぼ同じです。


実際、これは多かれ少なかれがやった方法であり、プロセス置換と組み合わせて、バックスラッシュを含むファイル名や末尾の空白を処理する機能を取り除いたものです。また、質問のタイトルには「ディレクトリを除外」と記載されており、この回答にディレクトリのみが含まれていることに注意してください。
G-マンは「元に戻すモニカ言う

ごめんなさい。私の間違い。修正しました。
トリスタンストーチ

-1

andと組み合わせるlocateとどうfileなりgrepますか?...

$ for f in `locate --regex --basename "xfce4-keyboard-overlay$"`; do file $f; done | grep -vi directory

私はテストしませんでしたが、それはfileすべての単一パスのプロセスを作成するため、遅いかもしれません。多くの場合、ロケートの結果の行が多いことに注意してください。私の現在のテストでは「gnome」を検索し、約73000のテストパスを提供しています。
フォルカーシーゲル

2
@Volker:それより悪いの$fは、それがファイルであるすべてに対して、fileプログラムが開くということです。そのファイルてそれから読み取ることです。あなたがする必要があるのは、非常に高価ですstat()。…………また、名前に「ディレクトリ」が含まれるファイル(「phone_directory」など)に対して誤った結果が得られます。……………(また、for f in `…`; do …構文はスペースを含む名前を処理できません。)
G-Manは「Reinstate Monica」と言います
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.