要件の最初の部分:
ex1234.Zip
から1つのファイルを抽出します。 ex1234.Zip
の構造と内容:
ex1234 (directory)
directory1
ex1234 (directory)
directory2
ex1234.csv
ex1234.csv
ファイルのみを抽出できるようにしたいのですが、名前がわかりません。
2番目の部分は、同じディレクトリにあるすべてのexXXXX.Zip
に対してこれを実行できるようにすることです。
ex1234.Zip
ex3245.Zip
ex8829.Zip
exXXXX.Zip…
出力は次のようになります。
ex1234.csv
ex3245.csv
ex8829.csv
exXXXX.csv
実際のサンプル:
$ less CW2178470.Zip アーカイブ:CW2178470.Zip zipファイルサイズ:26108バイト、エントリ数:26 -rw ---- 2.0 fat 108 bl defN 15- Aug-04 09:37 CW2178470/CW2178470.csv -rw ---- 2.0 fat 1363 bl defN 15-Aug-04 09:37 CW2178470/config/BusinessContactApprovers.csv -rw- --- 2.0 fat 158 bl defN 15-Aug-04 09:37 CW2178470/CW2178470/announcements.xml -rw ---- 2.0 fat 1037 bl defN 15-Aug-04 09:37 CW2178470/CW2178470 /Plan/plan.xml -rw---- 2.0 fat 141 bl defN 15-Aug-04 09:37 CW2178470/CW2178470/Plan/tasks.xml -rw ---- 2.0 fat 2408 bl defN 15-Aug-04 09:37 CW2178470/CW2178470/FI_Doc208411460_doc.xml -rw ---- 2.0 fat 215 bl defN 15-Aug-04 09:37 CW2178470/CW2178470/MessageBoard/nb_27482kst.26ihyzj_.htm -rw ---- 2.0 fat 2364 bl defN 15-Aug-04 09:37 CW2178470/CW2178470/MessageBoard/messageboard.xml -rw ---- 2.0 fat 1250 bl defN 15-Aug-04 09:37 CW2178470/CW2178470/te am.xml -rw ---- 2.0 fat 22016 bl defN 15-Aug-04 09:37 CW2178470/CW2178470/Doc208411460.doc -rw ---- 2.0 fat 9973 bl defN 15-Aug-04 09:37 CW2178470/CW2178470/audithistory.xml -rw ---- 2.0 fat 6731 bl defN 15-Aug-04 09:37 CW2178470/CW2178470/ws.xml -rw ---- 2.0 fat 308 bl defN 15-Aug-04 09:37 CW2178470/xsd/WSFolder.xsd -rw ---- 2.0 fat 4897 bl defN 15-Aug-04 09: 37 CW2178470/xsd/Task.xsd -rw ---- 2.0 fat 770 bl defN 15-Aug-04 09:37 CW2178470/xsd/ContractWorkspace.xsd -rw ---- 2.0 fat 4754 bl defN 15-Aug-04 09:37 CW2178470/xsd/AuditHistory.xsd -rw ---- 2.0 fat 25564 bl defN 15-Aug-04 09:37 CW2178470/xsd/CommonTypes。 xsd -rw ---- 2.0 fat 5657 bl defN 15-Aug-04 09:37 CW2178470/xsd/MessageBoard.xsd -rw ---- 2.0 fat 2471 bl defN 15- Aug-04 09:37 CW2178470/xsd/Plan.xsd -rw ---- 2.0 fat 337 bl defN 15-Aug-04 09:37 CW2178470/xsd/InternalContractW orkspace.xsd -rw ---- 2.0 fat 1045 bl defN 15-Aug-04 09:37 CW2178470/xsd/SalesContractRequest.xsd -rw ---- 2.0 fat 3133 bl defN 15-Aug-04 09:37 CW2178470/xsd/FolderItem.xsd -rw ---- 2.0 fat 906 bl defN 15-Aug-04 09:37 CW2178470/xsd/ContractRequest.xsd -rw ---- 2.0 fat 8973 bl defN 15-Aug-04 09:37 CW2178470/xsd/WorkspaceTypes.xsd -rw ---- 2.0 fat 4645 bl defN 15-Aug-04 09: 37 CW2178470/xsd/Team.xsd -rw ---- 2.0 fat 781 bl defN 15-Aug-04 09:37 CW2178470/xsd/SalesContractWorkspace.xsd 26ファイル、112005バイトの非圧縮、21940バイト圧縮:80.4% (END)
次のようにunzip
を使用できます。
_unzip -j file[.Zip] [file] [-x xfile]
_
ここで、_-j
_はジャンクパスを意味し、_file[.Zip]
_はアーカイブ名、_[file]
_は処理するアーカイブメンバー、_[-x xfile]
_は処理から除外するアーカイブメンバーのリストです。これらのオプションはすべて、manページで詳しく説明されています。
つまり、あなたの場合、たとえば次のように実行します:
_unzip -j ex1234.Zip '*/*.csv' -x '*/*/*'
_
_*.csv
_アーカイブの深度レベル2から_ex1234.Zip
_に一致するすべてのファイルを現在のディレクトリに抽出します(深度レベル3以下のアーカイブメンバーは_'*/*/*'
_が少なくとも2つに一致するパスを意味するため_/
_)。
ここで、現在のディレクトリにあるすべてのアーカイブを処理するには、次のコマンドを実行します。
_for zipfile in *.Zip; do unzip -j "$zipfile" '*/*.csv' -x '*/*/*'; done
_
現在のディレクトリの各アーカイブから_.csv
_ファイルを抽出します(そのため、_-j
_が必要です)。
特定のケースでは、レベル1の深さに_.csv
_がないため、次のように実行することもできます。
_for zipfile in *.Zip; do unzip -j "$zipfile" '*.csv' -x '*/*/*'; done
_
同じ結果が得られるはずです。
実際に抽出せずにどのファイル(アーカイブパス)が抽出されるかを模擬的に実行するには、_-j
_を_-qql
_に置き換えます。
_for zipfile in *.Zip; do unzip -qql "$zipfile" '*/*.csv' -x '*/*/*'; done
_
補足として、_-j
_オプションは省略できますiff抽出される_.csv
_ファイルは深度レベル1にありました(つまり、親ディレクトリがありません)。その場合は、単に次のように実行できます。
_for zipfile in *.Zip; do unzip "$zipfile" '*.csv' -x '*/*'; done
_
Fuse -basedファイルシステムを使用して、Zipファイルにディレクトリツリーとしてアクセスします。各Zipファイルをマウントしてから、通常の方法(シェルのワイルドカード、cp
コマンドなど)でアクセスします。
Fuse-Zip の場合:
_mkdir mnt
for z in *.Zip; do
Fuse-Zip -- "$z" mnt
set mnt/*.csv
if [ $# -gt 1 ]; then
echo "Skipping $z because it contains multiple .csv files"
Elif ! [ -e "$1" ]; then
echo "Skipping $z because it does not contain a .csv file"
else
cp -- "$1" "${z%.Zip}.csv"
fi
fusermount -u mnt
done
_
_Fuse-Zip
_の代わりに archivemount
を使用しても同じことができます。
[〜#〜] avfs [〜#〜] もあり、動作が異なります。_~/.avfs
_の下にファイルシステム全体のビューを作成します。このビューでは、_/path/to/foo.Zip
_というアーカイブファイルがある場合、_~/.avfs/path/to/foo.Zip#
_という名前のディレクトリとしてアクセスできます。
_mountavfs
cd "$HOME/.avfs$PWD"
for z in *.Zip; do
set -- "$z#/"*.csv
if [ $# -gt 1 ]; then
echo "Skipping $z because it contains multiple .csv files"
Elif ! [ -e "$1" ]; then
echo "Skipping $z because it does not contain a .csv file"
else
cp "$1" "${z%.Zip}.csv"
fi
done
_
配列でシェルを使用し、ワイルドカードが一致しない場合に空のリストを取得する方法を使用すると、少し読みやすいスクリプトを取得できます。たとえば、ksh93では、Fuse-Zipを使用します。
_#!/bin/ksh
mkdir mnt
for z in *.Zip; do
Fuse-Zip -- "$z" mnt
csv=(~(N)"$z/"*.csv)
if ((${#csv[@]} > 1)); then
echo "Skipping $z because it contains multiple .csv files"
Elif ((${#csv[@]} == 0)); then
echo "Skipping $z because it does not contain a .csv file"
else
cp -- "$1" "${z%.Zip}.csv"
fi
fusermount -u mnt
done
_
Zshでは、csv=($z/*.csv(N))
を使用します。 bashではcsv=($z/*.csv)
を使用しますが、最初に_shopt -s nullglob
_を実行します。
すべての名前が一致する必要があることをお勧めします。
その場合は、次のことを試してください。
for zipfile in ./*.Zip; do
base="$(basename "$zipfile" .Zip)"
unzip "$zipfile" "$base/$base.csv"
done
すべてのファイルがこのパターンに一致するという前提で-CW2178470.Zip
から、常にCW2178470/CW2178470.csv
を抽出する必要があります
これは比較的簡単です:
for i in ./*.Zip
do
SERIAL=$(echo "$i" | sed -e 's,^.*/,,' -e 's,.Zip$,,' )
unzip "$i" "${SERIAL}/${SERIAL}.csv"
done
それよりも賢いロジックが必要な場合は、おそらくPerl
とArchive::Zip
を調べて抽出します。
Debianが提供するunzipを試してみました:
UnZip 6.00 of 20 April 2009, by Debian. Original by Info-Zip.
for file in ex*.Zip
do
unzip -j $file '*.csv'
done