*.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

-inameは、glob に一致するファイルを検索し、大文字と小文字を区別しないことを意味します。問題は、glob が .*.htm*も検索することですhtmx

検出されないようにするには、htmxglob を分割する必要があります。

$ 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

regex は glob とは異なることに注意してください。特にドット ( .) とアスタリスク ( *) は glob と regex で意味が大きく異なります。

見るhttps://en.wikipedia.org/wiki/Glob_(プログラミング)#正規表現との比較詳細については。

答え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 修飾子 (最初の括弧内の頭文字)/によってディレクトリ パス名のみを含むようにフィルター処理され、リストはさらに、がtrue であるエントリのみを含むようにフィルター処理されます。この式 (は検査対象のディレクトリ パス名の 1 つ) は、ディレクトリにまたはファイル名サフィックス (大文字と小文字は区別されません) を持つ通常ファイルが少なくとも 1 つ含まれている場合に true になります。//[[ -n $REPLY/(#i)*.htm(l#)(#q.) ]]$REPLY.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)。ディレクトリ階層全体のすべてのディレクトリ パス名を/下から繰り返し、各ディレクトリのグロブを展開しようとします*.htm?(l)(これは、関心のある HTML ファイルと一致します)。このグロブの最初の一致が通常のファイル、またはそれへのシンボリック リンクである場合、ディレクトリ パス名とリストls -lが出力されます。

もしよろしければディレクトリ.htmonファイル名サフィックスを使用する場合.html、HTML サフィックスを持つ通常のファイル (または通常のファイルへのシンボリック リンク) を確実にキャッチするために、ループ内の拡張の一致を別のループでテストする必要があります。

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

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

ディレクトリをスキャンする方法によりfind、1 つ以上の連続した同一ディレクトリがリストされます。uniqそれぞれ 1 つだけが保持されます。

最後に、ディレクトリのリストを に渡してxargs、ディレクトリなしでコマンドを実行しないように指示し-r、区切り文字は改行文字であることを指定します-d '\n'。コマンドはls -l; です。お好みに合わせて変更してください。

ディレクトリのリストのみが必要で、ディレクトリの内容は必要ない場合は、次のxargs部分を削除します。

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

関連情報