web-dev-qa-db-ja.com

さまざまなアーカイブ形式のすべてのアーカイブファイルを再帰的に検索し、ファイル名パターンを検索します

せいぜい、私はこのような電話をしたいと思います:

$searchtool /path/to/search/ -contained-file-name "*vacation*jpg"

...このツールが

  • 指定されたパスを再帰的にスキャンします
  • 少なくともZip、rar、7z、tar.bz、tar.gzなどの「最も一般的な」アーカイブ形式でサポートされているすべてのファイルを取得します。
  • アーカイブのファイルリストをスキャンして、問題の名前パターンを探します(ここでは*vacation*jpg

検索ツール、tar、unzipなどの使用方法を知っています。これらをシェルスクリプトと組み合わせることができますが、シェルのワンライナーまたは専用ツールである可能性のあるシンプルなソリューションを探しています(GUIツールへのヒントは大歓迎ですが、私のソリューションはコマンドラインベースである必要があります)。

11
mdo

圧縮されたアーカイブを再帰的にgrepするにはどうすればよいですか?から適応

インストール [〜#〜] avfs [〜#〜] 、アーカイブ内の透過的なアクセスを提供するファイルシステム。最初にこのコマンドを1回実行して、マシンのファイルシステムのビューを設定します。このビューでは、ディレクトリのようにアーカイブにアクセスできます。

mountavfs

この後、/path/to/archive.Zipが認識されたアーカイブである場合、~/.avfs/path/to/archive.Zip#は、アーカイブのコンテンツを含むように見えるディレクトリです。

find ~/.avfs"$PWD" \( -name '*.7z' -o -name '*.Zip' -o -name '*.tar.gz' -o -name '*.tgz' \) \
     -exec sh -c '
                  find "$0#" -name "*vacation*.jpg"
                 ' {} 'Test::Version' \;

説明:

  • AVFSファイルシステムをマウントします。
  • 現在のディレクトリのAVFSビューである~/.avfs$PWDでアーカイブファイルを探します。
  • アーカイブごとに、指定されたシェルスニペットを実行します($0 =アーカイブ名、$1 =検索するパターン)。
  • $0#は、アーカイブ$0のディレクトリビューです。
  • 外側のfind{\}引数の内側の{}を置き換える場合は、{}ではなく-exec ;が必要です(実行するものとしないものがあります)。

またはzsh≥4.3の場合:

mountavfs
ls -l ~/.avfs$PWD/**/*.(7z|tgz|tar.gz|Zip)(e\''
     reply=($REPLY\#/**/*vacation*.jpg(.N))
'\')

説明:

  • ~/.avfs$PWD/**/*.(7z|tgz|tar.gz|Zip)は、現在のディレクトリとそのサブディレクトリのAVFSビューのアーカイブと一致します。
  • PATTERN(e\''CODE'\')は、PATTERNの各一致にCODEを適用します。一致したファイルの名前は$REPLYにあります。 reply配列を設定すると、一致が名前のリストに変わります。
  • $REPLY\#は、アーカイブのディレクトリビューです。
  • $REPLY\#/**/*vacation*.jpgは、アーカイブ内の*vacation*.jpgファイルと一致します。
  • N glob修飾子は、一致するものがない場合、パターンを空のリストに展開します。

AVFSソリューションよりも簡単なものが必要な場合は、Pythonスクリプトを実行して arkfind というスクリプトを作成しました。実際には、

$ arkfind /path/to/search/ -g "*vacation*jpg"

これは再帰的に行われるため、アーカイブ内のアーカイブを任意の深さで見ることができます。

9
detly

通常ソリューション:

find -iname '*.Zip' -exec unzip -l {} \; 2>/dev/null | grep '\.Zip\|DESIRED_FILE_TO_SEARCH'

例:

find -iname '*.Zip' -exec unzip -l {} \; 2>/dev/null | grep '\.Zip\|characterize.txt'

Resulsは次のようなものです。

foozip1.Zip:
foozip2.Zip:
foozip3.Zip:
    DESIRED_FILE_TO_SEARCH
foozip4.Zip:
...

hitsを含むZipファイルのみが必要な場合:

find -iname '*.Zip' -exec unzip -l {} \; 2>/dev/null | grep '\.Zip\|FILENAME' | grep -B1 'FILENAME'

[〜#〜] filename [〜#〜]ここでは2回使用されているため、変数を使用できます。

FindではPATH/TO/SEARCHを使用できます

2
Rodrigo Gurgel

IMHOの使いやすさもbashの1つである必要があります:

 while read -r Zip_file ; do echo "$Zip_file" ; unzip -l "$Zip_file" | \
 grep -i --color=always -R "$to_srch"; \
 done < <(find . \( -name '*.7z' -o -name '*.Zip' \)) | \
 less -R

とtar(これはテストされていません...)

 while read -r tar_file ; do echo "$tar_file" ; tar -tf  "$tar_file" | \
 grep -i --color=always -R "$to_srch"; \
 done < <(find . \( -name '*.tar.gz' -o -name '*.tar' \)) | \
 less -R
2
Yordan Georgiev

機能する別のソリューションはzgrepです

zgrep -r filename *.Zip
2
John Oxley

libarchivebsdtarは、これらのファイル形式のほとんどを処理できるため、次のことができます。

find . \( -name '*.Zip' -o     \
          -name '*.tar' -o     \
          -name '*.tar.gz' -o  \
          -name '*.tar.bz2' -o \
          -name '*.tar.xz' -o  \
          -name '*.tgz' -o     \
          -name '*.tbz2' -o    \
          -name '*.7z' -o      \
          -name '*.iso' -o     \
          -name '*.cpio' -o    \
          -name '*.a' -o       \
          -name '*.ar' \)      \
       -type f                 \
       -exec bsdtar tf {} '*vacation*jpg' \; 2> /dev/null

GNU findを使用して、次のように簡略化できます(大文字と小文字を区別せずに一致するように改善できます)。

find . -regextype egrep \
       -iregex '.*\.(Zip|7z|iso|cpio|ar?|tar(|\.[gx]z|\.bz2)|tgz|tbz2)' \
       -type f \
       -exec bsdtar tf {} '*vacation*jpg' \; 2> /dev/null

ただし、これらの*vacation*jpgファイルが見つかったアーカイブのパスは出力されません。その名前を印刷するには、最後の行を次のように置き換えます。

-exec sh -ac '
   for ARCHIVE do
     bsdtar tf "$ARCHIVE" "*vacation*jpg" |
       awk '\''{print ENVIRON["ARCHIVE"] ": " $0}'\''
   done' sh {} + 2> /dev/null

次のような出力が得られます。

./a.Zip: foo/blah_vacation.jpg
./a.Zip: bar/blih_vacation.jpg
./a.tar.gz: foo/blah_vacation.jpg
./a.tar.gz: bar/blih_vacation.jpg

またはzshを使用:

setopt extendedglob # best in ~/.zshrc
for archive (**/*.(#i)(Zip|7z|iso|cpio|a|ar|tar(|.gz|.xz|.bz2)|tgz|tbz2)(.ND)) {
  matches=("${(f@)$(bsdtar tf $archive '*vacation*jpg' 2> /dev/null)"})
  (($#matches)) && printf '%s\n' "$archive: "$^matches
}

.jarまたは.docxファイルのように、Zipまたはtgzファイルを装った他のファイル形式がいくつかあることに注意してください。それらをfind/zsh検索パターンに追加できます。bsdtarは拡張子を気にしません(のように、拡張子を決定するために拡張子に依存しませんファイルのタイプ)。

上記の*vacation*.jpgは、ファイル名だけでなく、完全なアーカイブメンバーパスで照合されるため、vacation.jpgだけでなくvacation/2014/file.jpgでも照合されることに注意してください。

ファイル名のみを照合するには、1つのトリックはextractモードを使用することです。-s(置換)を使用して、正規表現にpフラグを指定し、一致するファイルを探して、次のようにファイルが抽出されないことを確認します。

bsdtar -'s|.*vacation[^/]*$||' -'s|.*||' -xf "$archive"

Stderrにリストを出力し、すべての行に>>を追加することに注意してください。いずれの場合でも、bsdtarは、ほとんどのtar実装と同様に、改行やバックスラッシュ(\nまたは\\としてレンダリングされる)などの文字が含まれている場合、ファイル名を表示する場合があります。 )。

0