.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
。
検索を防ぐには、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
ディレクトリパス名とリストが出力されます。
持てるなら目次.htm
on ファイル名サフィックスを使用する場合は、.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
最初の部分は、大文字または小文字(globパターンを使用)で終わるすべてのファイルを検索し、見つかった各ファイルのディレクトリ()を1行find / '(' -iname '*.htm' -o -iname '*.html' ')' -printf '%h\n'
に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