特定の拡張子を持つすべてのファイルをgzipします


11

ファイル拡張子が.css、.htmlまたは.jsであるubuntu上のすべてのファイルをgzipしようとしています。最上位ディレクトリとすべてのサブディレクトリ。元のファイルを保持し、既存の場合は.gzファイルを上書きします。

したがって、n個のファイルがある場合、これらのn個のファイルを保持し、追加のn個のアーカイブファイルを作成します。1つだけではありません。

私の試みは、次のようなスクリプトを実行することでした。

gzip -rkf *.css
gzip -rkf *.html
... one line for each file extension

最初に、gzipするファイル拡張子ごとに、そのスクリプトに1行が必要です。大丈夫ですが、もっと良い方法を見つけたいと思います

2番目に重要なのは、機能しないことです。-rがジョブを実行する必要がありますが、サブディレクトリは変更されません。gzipファイルは最上位ディレクトリにのみ作成されます。

ここで何が欠けていますか?

ところで:以下は、冗長出力のバグですよね?-kおよび-vオプションを使用する場合

-k, --keep        keep (don't delete) input files
-v, --verbose     verbose mode

詳細な出力では、ファイルを置き換えると表示されますが、「置換」とは、置換後に元のファイルが存在しないことを意味します。とにかく、これは出力のみです。

$ ls
  index.html      subdir1  testfile      testfile.css.gz
  javaclass.java  subdir2  testfile.css
$ gzip -fkv *.css
  testfile.css:   6.6% -- replaced with testfile.css.gz
$ ls
  index.html      subdir1  testfile      testfile.css.gz
  javaclass.java  subdir2  testfile.css

1
-r設計どおりに動作します。man gzipから:ディレクトリ構造を再帰的に移動します。コマンドラインで指定されたファイル名のいずれかがディレクトリの場合、gzipはそのディレクトリに降りて、そこで見つかったすべてのファイルを圧縮します(または、gunzipの場合は解凍します)。(強調鉱山)
デニス14

OK。したがって、-rはXYZ.cssという名前のディレクトリに入ります。その場合、再帰は予期したとおりに設計されていません。
サディク14

回答:


7

forループを使用してすべてのファイルを検索し、圧縮することができます。

for i in `find | grep -E "\.css$|\.html$"`; do gzip "$i" ; done

ありがとうございました!この-rオプションは機能せず、機能-k-fているので、次のように使用できますfind | grep -E "\.css$|\.html$"。gzip -vkf "$ i"を実行します。完了しました
Sadik

@サディク:注意してください!ファイルの名前にスペースが含まれている場合、このアプローチは機能しません。
デニス14

なぜそうではないのか説明できますか?
サディク14

1
@Sadik:`...`リストではなく文字列を提供します。for内部フィールド区切り文字($IFS)を使用して、その文字列を分割する場所を決定します。デフォルトでは、改行、タブ、スペースで分割されるため、というファイルがある場合new style.cssは、コマンドgzip newとコマンドgzip style.cssが実行されます。
デニス14

1
@Sadik、デニスは正しいです。ループのexport IFS=$'\n'直前に簡単な回避策を実行できるからforです。
mndo 14

14

私は使うだろう

find /path/to/dir \( -name '*.css' -o -name '*.html' \) -exec gzip --verbose --keep {} \;

変更nameinameあなたは大文字と小文字を区別せずに拡張を一致させたい場合(つまり含ん.CSSおよび/または.HTML拡張)。/path/to/dir現在のディレクトリから再帰検索を開始する場合は、を省略できます。


2
--keepスイッチについて疑問に思っている人のために、はい、元のファイルが保持されます。gzipで圧縮した後で削除する場合は、省略します。
ベンジョンソン

4

ファイルのリストを取得するには:

find -type f | grep -P '\.js|\.html|\.css'

そして、これらすべてのファイルをgzipするには:

find -type f | grep -P '\.js|\.html|\.css' | tar cvzf archive.gz -T -

これtarは、ファイル自体ではなく、 による出力としてファイルのリストではありませんfindか?
ジョス14

質問を編集して、css、html、またはjsファイルごとにアーカイブファイルを作成することを明確にしました。
サディク14

2
@Jos no -Tオプションtarは、入力をファイル名として処理します。
カオス14

@chaosああ、ありがとう。今日は何かを学びました。
ジョス14

2

私はsteeldriverの回答を使用しましたが、--best--forceオプションでそれを完了するのが好きです。

cd任意のフォルダーにこのコードを入力します。一致するすべてのファイルがgzip圧縮されます。

find . \( -name '*.css' -o -name '*.js' \) -exec gzip --verbose --keep --best --force {} \;
  • --best最適な圧縮率を得るために使用します。
  • --force既にgzip圧縮されたファイルがあるかどうかを尋ねることなく上書きに使用します。

1

globstarを使用できます。

globstarシェルオプションが有効になって、あなたが必要とするすべてですgzip -vk **/*.{css,html}

Bashシェルには、globstarを使用して再帰的なglobを作成できるオプションがあります**shopt -s globstar有効にします。ただし、後で実行する他のコマンドに対してはそうしたくないのでgzip 、代わりにサブシェルでコマンドを実行できます。

このコマンドはgzip、すべてのだ.css.html任意のそのサブディレクトリのいずれかの現在のディレクトリ内のファイルを自分の(元のファイルを維持する、などのサブディレクトリ、-k()、それはやっている何を言って-v):

(shopt -s globstar; gzip -vk **/*.{css,html})

ファイル名の大文字と小文字を区別せずに一致させ、一部またはすべての文字が大文字になっている拡張子を含める場合は、nocaseglobシェルオプションを有効にすることもできます。

(shopt -s globstar nocaseglob; gzip -vk **/*.{css,html})

;2つのコマンドを分離し、外側のコマンドにより( )サブシェルで実行されます。サブシェルでシェルオプションを設定しても、呼び出し元のシェルでは設定されません。あなたがいる場合有効にしたいglobstar、あなたは実行することができますshopt -s globstar。次に、コマンドを実行するだけです:

gzip -vk **/*.{css,html}

あなたは無効にすることができglobstarshopt -u globstar。で現在有効になっているかどうかを確認できshopt globstarます。

使い方

このgzipコマンドの動作の鍵は、シェルがコマンドを展開して、ディレクトリ階層内の各ファイルと一致する名前のリストを作成し、これらの各ファイル名を引数としてに渡すことgzipです。

  • ブレース展開は変わり**/*.{css,html}**/*.css **/*.html
  • そして、グロブ(現在のディレクトリの下にアクセス可能なファイルの名前に展開さにこれら二つのパターンを**のために、globstarそのファイル名が何も(で構成さ)*)指定された接尾辞(続く.cssか、.htmlこの場合)。

これは、名前がで始まる.ファイルや、この方法で名前が付けられたディレクトリにあるファイルとは一致しません。そのようなHTMLファイルやCSSファイルはおそらくないでしょうし、もしそうなら、おそらくそれらを含めたくないでしょう。ただし、それらを含める場合は、必要に応じて明示的に一致させることができます。たとえば、に変更**/*.{css,html}する**/{,.}*.{css,html}と、開始するファイルが含まれますが.、まだ存在するフォルダー検索されません。

名前で始まるファイルと、名前で始まる.ディレクトリ内のファイルの両方を.含める場合、よりクリーンで簡単な方法がありdotglobます。シェルオプションを有効にします。

(shopt -s globstar dotglob; gzip -vk **/*.{css,html})

または、大文字と小文字を区別しないマッチング、および次で始まるファイル名のマッチングが必要な場合.

(shopt -s globstar nocaseglob dotglob; gzip -vk **/*.{css,html})

非常にまれですが、**長すぎるものに拡張することは可能です。

あなたが持っている場合は、巨大なこの方法を指定されたファイルの数を、これは、それが長すぎるので、シェルはコマンドラインを構築することができないことを説明するエラーメッセージを表示して失敗することがあります。(数千のファイルがある場合でも、通常これ問題ではありません。)

gzip まったく呼び出されないので、半分の仕事を得ることができません。

このエラーが発生した場合、あなたはそれを心配している場合、または、あなたが使用することができfind-exec、どちらかとsteeldriverが記述する(と{} \;)またはように私は(と以下の記述します{} +)。

あなたは使うことができfind-exec、アクションと+効率化のために。

このgzipコマンドは、圧縮する複数のファイルの名前の指定をサポートしています。しかし、このfindコマンドはうまく機能し、多くのファイルがない限り遅くなりませんがファイルごとにgzip 1回コマンドを実行し ます。

find . \( -name \*.css -o -name \*.html \) -exec gzip -vk {} \;

これは機能し、間違いなく使用できます。(.現在のディレクトリから検索します。それ以外に、steeldriverの非常に良い答えでコマンドを書く方法は実際には少し異なります。好きなスタイルを使用できます。)

また、find複数のファイル名をgzip必要な回数だけ渡して実行することもできます。これはほとんどの場合1回だけです。それを行うには、の代わりにを使用します+\;+引数には、直後に来る必要があります{}。もしあれば、追加のファイル名にfind置き換え+ます。

find . \( -name \*.css -o -name \*.html \) -exec gzip -vk {} +

+一致するファイルが少数しかない場合でも使用できgzipます。それらのファイルが多数ある場合は、ファイルごとに個別の呼び出しを行うよりも著しく高速です。

以下のようsteeldriverが言及、あなたが使用することができる-iname代わりに-name、名前が終わりのようなファイルと一致する.css.htmlが異なる大文字と小文字を。これnocaseglobは、globstar上記のベースの方法で有効にすることに対応します。

最後に、おそらくで始まる一致するファイルまたはディレクトリがありません.。ただし、その場合、find自動的に含まれます。それらを除外したい場合(globstar上で詳述した-basedの方法dotglobがオフのときに起こるように)、次のことができます

find . -not -path '*/.*' \( -name \*.css -o -name \*.html \) -exec gzip -vk {} +

globstar上記で説明した- ベースの方法は、特に.デフォルトであるため、で始まるディレクトリとファイルを除外する場合に記述が簡単です。

何をしていない行うには...

ファイル名には、パス区切り文字/ヌル文字を除く任意の文字を含めることができます。奇妙なファイル名を壊す多くのテクニックが存在し、それらは通常常に機能するテクニックよりも複雑です。そのため、特定の状況では大丈夫だとわかっている(または知っていると思う)場合でも、それらを避けることをお勧めします。そしてもちろん、スペースを含む特別に扱われる可能性のある文字を含むファイル名がある場合は、それらを使用してはいけません。

を使用する場合、またはそれ以外の場合ではなく、改行の代わりにパスの間にヌル文字を配置するための同様のアクションを使用する場合、findそれを処理する別のコマンドに出力を安全にパイプすることができます。ファイル名には改行を含めることができます(ただし、意図的にファイルに名前を付けることはお勧めしません)。コマンドアクション-明示的なアクションを使用してfindコマンドを含む、それ以来、デフォルトでは-安全にパイプされたか、そうでない場合は、ファイルに対して実行する処理という別のコマンドに提供することができる出力を生成しません。-print0find-print-print

アクションでfind生成された出力は、-print0安全にパイプされる可能性がありますxargs -0-0フラグはxargs、nullで区切られた入力を予期するように指示します)。


0

フォルダー/サブフォルダー内のすべてのファイルを再帰的に圧縮するには:

gzip -r `find . -type f -name "*.html"` 

解凍するには:

gunzip -r `find . -type f -name "*.gz"` 

このコマンド置換ベースの方法は、頻繁に壊れ、非常にひどくなります。問題は、スペースまたは他の空白を含むファイル名が分割され、複数のファイル名として扱われることです。(これらのコマンドは` `構文を使用して記述されていますが、$( )構文を使用する場合にも問題は完全に当​​てはまります。)
エリアカガン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.