ZAPAnet総合情報局 > ZAPAブログ2.0 > 特定のファイル一覧を出力するときのメモ

特定のファイル一覧を出力するときのメモ

2020年06月20日 プログラミングTIPS
Linuxサーバー内のある特定のファイルの一覧を出力したくなりました。例えば、「*.html」とか「*.php」とかです。Linuxにはtreeコマンドがあったなと思ってCentOS8で打とうとしたらありませんでした。ということで、まずはtreeコマンドのインストールから。CentOS8ではインストールコマンドが今までの「yum」から「dnf」に変わっています(「yum」でも動きます)。
dnf install tree

ディレクトリの情報はいらなくて、全ての階層のサブディレクトリまでファイルパスとファイル名だけ出てきてくれれば良かったので、「.html」のファイルを全て出力するために以下のようなコマンドを打ってみました。
tree -f -i  ./ -P '*.html' > html_list.txt
これでファイル一覧がhtml_list.txtに出力されるかと思ったら、htmlファイルだけでなくディレクトリ情報も一緒に出力されてしまいました。

ファイルだけをスマートに出力させたかったのですが、できていなかった上にもうローカルにダウンロードしてしまったので、今度は特定のファイルを含まない行を全て削除する方法を考えてみました。

今使っているWindows用のエディタ「Sublime Text」は複数行置換や正規表現などに対応していて高機能です。それならと、「特定の文字列を含まない行」を置換できるのではないかと考えました。探してみたらすぐ見つかりました。
Sublime Textで「特定の文字列を含まない行」は以下のようにして取り出せます。
^(?!.*文字列).+$
「html以外の行を削除」というのであれば、Sublime Text3で正規表現置換をONにして、以下のように置換すればOKです(置換後の文字列は空白です)。
^(?!.*html).+$\n
これで、「html」で終わっているファイルを全て取り出せました。ファイルパスは相対パスになっているため、ここからドメイン名に置換すると、そのまますべてのhtmlファイルのURLになります。sitemapで静的なhtmlファイルの一覧を作るときに、この方法を使いました。

ついでに、sitemapは一般的に以下のような構造になっています。
<url>
  <loc></loc>
  <priority></priority>
  <changefreq></changefreq>
  <lastmod></lastmod>
</url>

出力した全てのHTMLファイルのパスが一行ずつ並んでいるのなら…
sublimetext
上記のようにSublime Textで複数行置換することによって、簡易的な(priority、lastmod、changefreqの情報を持たない)サイトマップを作れます。詳しい情報は持たず、とりあえずURLを羅列しただけのHTMLファイルのサイトマップを作りたいときに使えます。

treeコマンドを使わず、Linux上でスマートに出力させる方法を考えた方が良かったのかもしれませんが、とりあえず目的は達成できたのでよしとします。

追記1:grepで出力

Twitterでgrepを使った方法についてアドバイスいただきました。
「grepはファイル内の文字列を調べるので、リッチすぎるのでは?」と思って手を出していませんでした。grepをオススメされたので、grepでファイル一覧を取り出す方法について考えてみました。全てのサブディレクトリまでのhtmlファイルを取り出すために、以下のオプションを付けることにしました。
-i(--ignore-case)
大文字小文字を区別しない
-r(--recursive)
サブディレクトリ内も再帰的に検索する
--include
特定の拡張子のみ対象にする
--includeオプションで拡張子を指定できるため、サブディレクトリまで全て検索しても、動作が異常に重くなることはないです。正しいhtmlファイルには、「</html>」などの「html」という文字が必ず入っています。ファイル内に大文字小文字を区別しないhtmlの文字列が含まれているファイルを抜き出してみることにしました。作ったコマンドは以下の通りです。
grep -irl --include='*.html' html ./* > html_list.txt
これで、今いるディレクトリ以下にある全ての「ファイル内にhtmlの文字列がある.htmlファイル」の一覧を出力できました。検索する対象のファイル拡張子が決まっているのなら、grepを使った方がスマートでした。

追記2:findで出力

grepでファイル内まで検索するマジメな検索方法を考えたので、ついでにfindで検索してみる方法も考えてみました。本当はこれを最初にやるべきでしょう。
find -type f -name "*\.html" | sort > html_list.txt
「-type f」でディレクトリを除外してファイル限定、「-name "*\.html"」で.htmlが含まれるファイル限定にしています。そのまま出力すると順番がバラバラなので、「| sort」で名前順にしています。ディレクトリ以下の特定の拡張子ファイル一覧を取り出したいときはこのコマンドでOKですね。

ファイル内の文字列までチェックして一覧を取り出したい場合はgrepで、ファイル名だけで一覧を取り出したい場合はfindで。一つ賢くなりました。