*.htmlファイルを含むすべてのディレクトリを一覧表示し、ディレクトリ内のファイルを一覧表示します。

*.htmlファイルを含むすべてのディレクトリを一覧表示し、ディレクトリ内のファイルを一覧表示します。

.htmケースが完成したかどうかにかかわらず、HTML文書を含むすべてのディレクトリのリストを取得したいと思います.html

私は試した:

find / -type d -ls | tr -s [:blank:] | cut -d ' ' -f 11 | grep -i -e "*.htm" -e "*.html"

ただし、ディレクトリのみが一覧表示されます。このディレクトリの内容を一覧表示する必要がありますが、方法がわかりません。

その後、次のことを試しました。

find / -type d -exec ls -l {} \; | tr -s [:blank:] | cut -d ' ' -f 9 | grep -i -e ".htm" -e ".html"

その項目が見つかりましたが、その項目があるディレクトリをどのように印刷しますか?

答え1

サンプル出力を含むいくつかの可能なコマンドは次のとおりです。

最も簡単な:

$ find / -iname "*.htm*"
foo/a.HTM
foo/b.HTML
foo/b.html
foo/x.htmx
foo/a.htm
bar/a.htm

-inameglobと一致するファイルの検索を表し、大文字と小文字を区別しません。問題はglobが*.htm*それを発見することですhtmx

検索を防ぐには、htmxグローバルを分割する必要があります。

$ find / -iname "*.htm" -o -iname "*.html"
foo/a.HTM
foo/b.HTML
foo/b.html
foo/a.htm
bar/a.htm

または grep を使用して正規表現を使用します。

$ find / | grep -i "\.html*$"
foo/a.HTM
foo/b.HTML
foo/b.html
foo/a.htm
bar/a.htm

正規表現はglobとは異なります。特に、点(.)とアスタリスク(*)はglobと正規表現で非常に異なる意味を持ちます。

バラよりhttps://en.wikipedia.org/wiki/Glob_(programming)#Compared_to_regular_expressionsより多くの情報を知りたいです。

答え2

使用zsh:

setopt extendedglob nullglob
for pathname in /**/*(/e{'[[ -n $REPLY/(#i)*.htm(l#)(#q.) ]]'}); do
    printf '%s:\n' $pathname
    ls -l $pathname
done

.htmこれにより、名前または末尾の通常のファイル.html(大文字と小文字が区別されていない)を含む各ディレクトリのパス名が印刷され、その後にls -lそのディレクトリへの出力が表示されます。

ループは/HTMLファイルを含む各ディレクトリを通過します。これは、ディレクトリ階層全体のすべてのエントリ/**/*と一致するglobを使用してこれを行います。/リストは/ディレクトリパス名のみを含むようにglob修飾子(最初の角かっこの最初の文字)でフィルタリングされ、/リストは[[ -n $REPLY/(#i)*.htm(l#)(#q.) ]]trueのエントリのみを含むようにさらにフィルタリングされます。この式(ここで確認しているディレクトリパス名の1つ)は、ディレクトリに、またはファイル名のサフィックス(大文字と小文字を区別しない)を持つ1つ以上の$REPLY一般的なファイルが含まれている場合はtrueです。.htm.html

e{...}ワイルドカードパターン部分は、おそらくより簡潔に書くことができます。


使用bash:

shopt -s globstar nullglob extglob nocaseglob
for pathname in /**/*/; do
    set -- "$pathname"/*.htm?(l)
    if [[ -f $1 ]]; then
        printf '%s:\n' "${pathname%/}"
        ls -l "$pathname"
    fi
done

これはglobstarシェルオプションを使用して**グロービングモード(デフォルトではzshシェルで有効)を有効にします。これは、下から上にディレクトリ階層全体のすべてのディレクトリパス名を繰り返し、/各ディレクトリでglobを拡張しようとします*.htm?(l)(関心のあるHTMLファイルと一致します)。 globの最初の出現が通常のファイルまたはファイルへのシンボリックリンクの場合、ls -lディレクトリパス名とリストが出力されます。

持てるなら目次.htmon ファイル名サフィックスを使用する場合は、.htmlHTML サフィックスを含む一般ファイル (または一般ファイルへのシンボリックリンク) がキャプチャされることを確認するために、別のループでループ内の拡張マッチングをテストする必要があります。

shopt -s globstar extglob nocaseglob
for pathname in /**/*/; do
    for match in "$pathname"/*.htm?(l); do
        if [[ -f $match ]]; then
            printf '%s:\n' "${pathname%/}"
            ls -l "$pathname"
            break
        fi
    done
done

nullglobこれ以上依存しないので、このバリエーションからシェルオプションを削除しました。


POSIXshシェルはglobにアクセスできないため、**それを使用findして循環ディレクトリパス名を生成する必要があります。

find / -type d -exec sh -c '
    for pathname do
        for match in "$pathname"/*.[hH][tT][mM] "$pathname"/*.[hH][tT][mM][lL] ; do
            if [ -f "$match" ]; then
                printf "%s:\n" "${pathname%/}"
                ls -l "$pathname"
                break
            fi
        done
    done' sh {} +

これは含まれているスクリプトのパス名ジェネレータとしてfind機能し、sh -cディレクトリのパス名を提供します。

スクリプトsh -cは、答えの2番目のバリエーションとほぼ同じことを行いますbash。つまり、必要な名前と一致する必要があるglobの拡張子を繰り返して、各名前をテストして通常のファイル(またはそれを指すシンボリックリンク)であることを確認します。 )。ファイルが見つかると、ディレクトリパス名とls -l出力が順番に印刷されます。

答え3

使用することをお勧めします

find / '(' -iname '*.htm' -o -iname '*.html' ')' -printf '%h\n' | uniq | xargs -r -d '\n' ls -l

最初の部分は、大文字または小文字(globパターンを使用)で終わるすべてのファイルを検索し、見つかった各ファイルのディレクトリ()を1行find / '(' -iname '*.htm' -o -iname '*.html' ')' -printf '%h\n'に1つずつ印刷します。.htm.html%h

ディレクトリの検索方法により、find1つ以上の連続した同じディレクトリが一覧表示され、各uniqタイプの1つだけが保持されます。

最後に、ディレクトリのリストを提供し、xargsディレクトリなしでコマンドを実行しないように-r区切り記号を改行文字と呼びます-d '\n'。コマンドはls -l;必要に応じて編集してください。

ディレクトリの内容ではなくディレクトリのリストのみが必要な場合は、次のxargsセクションを削除してください。

find / '(' -iname '*.htm' -o -iname '*.html' ')' -printf '%h\n' | uniq

関連情報