私はuse Test::Version
cpanのどのモジュールを見つけようとしています。だから私はminicpan
それをミラーリングするために使用しました。私の問題は、ダウンロードされたアーカイブを反復処理し、アーカイブ内のファイルをgrepする必要があることです。誰も私にこれをどうやってやるか教えてもらえますか?できれば、アーカイブ内のファイルとその行を教えてくれる方法で。
(注:それらはすべてtarballであるわけではなく、一部はzipファイルです)
私はuse Test::Version
cpanのどのモジュールを見つけようとしています。だから私はminicpan
それをミラーリングするために使用しました。私の問題は、ダウンロードされたアーカイブを反復処理し、アーカイブ内のファイルをgrepする必要があることです。誰も私にこれをどうやってやるか教えてもらえますか?できれば、アーカイブ内のファイルとその行を教えてくれる方法で。
(注:それらはすべてtarballであるわけではなく、一部はzipファイルです)
回答:
OK、Unixの哲学を適用しましょう。このタスクのコンポーネントは何ですか?
grep
。find
。ほとんどのUNIXプログラムはファイルを操作します。したがって、アーカイブコンポーネントを簡単に操作するには、ファイルとしてそれらにアクセスする必要があります。つまり、ディレクトリとしてアクセスする必要があります。
AVFSファイルシステムのすべてのアーカイブファイルは、ファイルシステムのビュー提示/path/to/foo.zip
ディレクトリとしてアクセス可能です~/.avfs/path/to/foo/zip#
。AVFSは、最も一般的なアーカイブファイル形式への読み取り専用アクセスを提供します。
mountavfs
find ~/.avfs"$PWD" \( -name '*.zip' -o -name '*.tar.gz' -o -name '*.tgz' \) \
-exec sh -c '
find "$0#" -name "*.pm" -exec grep "$1" {\} +
' {} 'Test::Version' \;
fusermount -u ~/.avfs # optional
説明:
~/.avfs$PWD
。これは、現在のディレクトリのAVFSビューです。$0
=アーカイブ名と$1
=検索するパターンを使用)。$0#
は、アーカイブのディレクトリビューです$0
。{\}
{}
外側の引数が内部でfind
代用される場合に必要となるのではなく(そうする人もいれば、そうでない人もいます)。{}
-exec ;
またはzsh≥4.3の場合:
mountavfs
grep 'Test::Version' ~/.avfs$PWD/**/*.(tgz|tar.gz|zip)(e\''
reply=($REPLY\#/**/*.pm(.N))
'\')
説明:
~/.avfs$PWD/**/*.(tgz|tar.gz|zip)
現在のディレクトリとそのサブディレクトリのAVFSビューのアーカイブに一致します。PATTERN(e\''CODE'\')
PATTERNの各一致にCODEを適用します。一致したファイルの名前はです$REPLY
。reply
配列を設定すると、一致が名前のリストに変わります。$REPLY\#
アーカイブのディレクトリビューです。$REPLY\#/**/*.pm
.pm
アーカイブ内のファイルと一致します。N
グロブ修飾子は一致しない場合、パターンは空のリストに展開されます。~/.avfs
)があり、各アーカイブへのアクセスは自動的に行われます(~/.avfs/path/to/archive.zip\#
マウントポイントではなく、AVFSファイルシステム上の通常のディレクトリです)。確かに、アクセスする各アーカイブはパフォーマンスに少し影響を与えますが、それは問題に固有のものです。
find: missing argument to
-exec'`とzshからこれの多くを得るためzsh: Input/output error: Data-Maker-0.27
挑戦をありがとう、私は思いついた:
#!/bin/bash
#
# tarballs to check in
find authors/ -type f | while read tarball; do
# get list of files in tarball (not dirs ending in /):
tar tzf $tarball | grep -v '/$' | while read file; do
# get contents of file and look for string
tar -Ozxf conform.tar.gz $file | grep -q 'Text::Version' && echo "Tar ($tarball) has matching File ($file)"
done
done
tar (child): conform.tar.gz: Cannot open: No such file or directory tar (child): Error is not recoverable: exiting now tar: Child returned status 2 tar: Error is not recoverable: exiting now
たぶん私の答えは誰かに役立つでしょう:
#!/bin/bash
findpath=$(echo $1 | sed -r 's|(.*[^/]$)|\1/|')
# tarballs to check in
find $findpath -type f | while read tarball; do
# get list of files in tarball (not dirs ending in /):
if [ -n "$(file --mime-type $tarball | grep -e "application/jar")" ]; then
jar tf $tarball | grep -v '/$' | while read file; do
# get contents of file and look for string
grepout=$(unzip -q -c $tarball $file | grep $3 -e "$2")
if [ -n "$grepout" ]; then
echo "*** $tarball has matching file ($file):"
echo $grepout
fi
done
elif tar -tf $tarball 2>/dev/null; then
tar -tf $tarball | grep -v '/$' | while read file; do
# get contents of file and look for string
grepout=$(unzip -q -c $tarball $file | grep $3 -e "$2")
if [ -n "$grepout" ]; then
echo "*** $tarball has matching file ($file):"
echo $grepout
fi
done
else
file=""
grepout=$(grep $3 -e "$2" $tarball)
if [ -n "$grepout" ]; then
echo "*** $tarball has matching:"
echo $grepout
fi
fi
done