名前 - パスを検索

名前 - パスを検索

私には木があります。

.
├── 1
│   └── a
│       └── script.a.sh
├── 2
│   └── a
│       └── script.b.sh
...
└── a
    └── script.sh

私は見つけるべきですscript.*.sh。私は以下を実行します./a/script.sh

#!/bin/bash
#

path="/tmp/test"

readarray files < <(find ${path} -path  "*/a/script.*.sh")

if [ ${#files[@]} -ne 0 ]
then
  for file in "${files[@]}"
  do
    echo ${file}
  done
fi

出力:

/tmp/test/1/a/script.a.sh
/tmp/test/2/a/script.b.sh

これは有効なスクリプトです!

find ${path} -path "*/a" -name "script.*.sh"ただし、findコマンドをスクリプトに変更すると、何も出力されません。

私のロジックは/tmp/test/*/a/script.*.sh私が言うパターンを持つすべてのファイルを探しますfind ${path} -path "*/a" -name "script.*.sh"

現在残っている質問は次のとおりです。

  1. find ${path} -path "*/a" -name "script.*.sh"コマンドは実際に何をしますか?
  2. にデバッグモードがありますかfind?私の言葉は、私が何を言っているのかを理解する方法を意味します(例:検索するパス、no find . -name "*te.st*"、just ./*/*te.st*)。
  3. -name、同じコマンドライン(必要なケース、はい、説明)にありますか-path?それとも相互排他的ですか?それとも-path拡張バージョンと言えますか-name

manはい、はい、およびを使用できますgoogle。また、これらのソースからすべての質問に対する完全な答えが見つかりませんでした。

答え1

-pathGNUバージョンの引数は、find開始ディレクトリを含むアクセスされるオブジェクトのフルパスに適用されるパターンを指定します。

パターンはパターンですが、スラッシュは特に扱われません。たとえば、パスとパターンのa/b/c/d一致ですa*d

これはシェルステートメントのパターンcaseマッチングと似ています。

$ case a/b/c/d in a*d ) echo match;; esac
match

パス名拡張でパターンマッチングの代わりに。

$ echo a*d # will not match an a/b/c/d file accessible in this directory!

たとえば、次のようになります。

find /etc -path '*.conf'

一致して印刷されます/etc/foobar/foobar.conf。パスに出会うと、パスはパターンと一致します。

したがって:

  1. 質問:find ${path} -path "*/a" -name "script.*.sh"何をしますか?

    答え:何も見つかりません。-pathで終わるパスと一致するため、/aで終わるscript.*.shディレクトリエントリを一致させることはできませんa-pathand述語は-name暗黙の論理ANDにリンクされているため、結果は空です。

  2. 開始位置はオプションです。省略findできます。シェル構文(引用符なしの引数として使用される場合)は、ファイル名拡張子を使用してシェルによって拡張されます。または、一致するものがない場合は、そのままにしておくこともできます。find -name '*.txt'find . -name '*.txt'./*/*te.st*find

  3. -pathQ:ライブと-name同じコマンドラインにありますか?

    答え:もちろん可能です。ただし、「and」と組み合わせて競合が発生すると、結果が空になる可能性があります。 find -path X -name Y意味find -path X -a -name Y -a -print: アクセスしたパスが一致しないX場合そしてアクセスされているディレクトリエントリが一致すると、Yパスが印刷されます。X一致する名前で終わるY一致するパスがないと、-print述語(暗黙的または明示的)に到達できません。何も印刷できません。

答え2

find ${path} -path "*/a" -name "script.*.sh"ただし、findコマンドをスクリプトに変更すると、何も出力されません。

実際にはそうではありません。述語と一致するファイルは述語-path "*/a"とも一致できません-name "script.*.sh"

私のロジックは/tmp/test/*/a/script.*.sh私が言うパターンを持つすべてのファイルを探しますfind ${path} -path "*/a" -name "script.*.sh"

あなたが仮定している$path値は/tmp/test。この場合、なぜ仕事をそんなに複雑にするのか分かりません。 globを使って目的のパスを正確に説明できるので、find完全に省略したいと思います。

files=("${path}"/*/a/script.*.sh)

ただし、これを行うには、findこの場合、合計を組み合わせることは意味がありません-name-pathすでに観察したように、元のコマンドはこれをfind行います。そしてもっとシンプルで明確です。

あるいは、部分パスマッチングを元のリストに移動することもできます。

find ${path}/*/a -maxdepth 1 -name  "*script.*.sh"
  1. find ${path} -path "*/a" -name "script.*.sh"コマンドは実際に何をしますか?

${path}ルートにルートがあるサブツリーで、パス(で始まる${path})がパターンと一致し、デフォルト名がパターン*/aと一致するファイルを検索しますscript.*.sh。それぞれ完了しました。これら2つの条件を満たすすべてのファイルのパスは印刷されますが、同じファイルが両方の条件を同時に満たすことはできないため、何も印刷されません。

  1. にデバッグモードがありますかfind?私の言葉は、私が何を言っているのかを理解する方法を意味します(例:検索するパス、no find . -name "*te.st*"、just ./*/*te.st*)。

POSIXにはデバッグツールはありませんが、findutilsとfindutilsの両方がタグfind付けされているため、GNU findutilsバージョンを使用していることはほぼ確実です。この実装linuxubuntufindするデバッグツールが文書化されています。マンページ。あなたはこのオプションを探しています-D。どのように役立つかはわかりませんが、最大のデバッグ情報を取得するには、開始点リストの-D all前にコマンドを追加できます。find

  1. -name、同じコマンドライン(必要なケース、はい、説明)にありますか-path?それとも相互排他的ですか?それとも-path拡張バージョンと言えますか -name

はい、一緒に使用することができ、時には組み合わせることが合理的かもしれません。しかし、あなたを混乱させることができるのは

  • 彼ら独立
  • -pathテストみんなディレクトリ部分だけでなくパス。おそらくあなた-pathがそうしたのかと尋ねたときの状況はそうでした-name

-path述語が実際に選択したいファイルと一致しないため、結合しようとすると失敗します。しかしこれはうまくいきます:

find ${path} -path  "*/a/*" -name "script.*.sh"

-o-aさらに、暗黙的または明示的(「and」)の代わりに連結詞(「または」を意味)を使用したり、1つまたは2つの述部を否定する組み合わせで使用することができます-not

関連情報