私の要件の最初の部分:
私はそれから単一のファイルを抽出したいと思いますex1234.zip
。構造と内容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
実際のサンプル:
$ 少ないCW2178470.zip アーカイブ: CW2178470.zip Zipファイルサイズ:26108バイト、アイテム数:26 -rw---- 2.0 fat 108 bl defN 2004年8月15日 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 2004年8月15日 09:37 CW2178470/CW2178470/announcements.xml -rw---- 2.0 fat 1037 bl defN 2004年8月15日 09:37 CW2178470/CW2178470/Plan/plan.xml -rw---- 2.0 fat 141 bl defN 2004年8月15日 09:37 CW2178470/CW2178470/Plan/tasks.xml -rw---- 2.0 fat 2408 bl defN 2004年8月15日 09:37 CW2178470/CW2178470/FI_Doc208411460_doc.xml -rw---- 2.0 fat 215 bl defN 2004年8月15日 09:37 CW2178470/CW2178470/MessageBoard/nb_27482kst.26ihyzj_.htm -rw---- 2.0 fat 2364 bl defN 2004年8月15日 09:37 CW2178470/CW2178470/MessageBoard/messageboard.xml -rw---- 2.0 fat 1250 bl defN 2004年8月15日 09:37 CW2178470/CW2178470/team.xml -rw---- 2.0 fat 22016 bl defN 2004年8月15日 09:37 CW2178470/CW2178470/Doc208411460.doc -rw---- 2.0 fat 9973 bl defN 2004年8月15日 09:37 CW2178470/CW2178470/audistory.xml -rw---- 2.0 fat 6731 bl defN 2004年8月15日 09:37 CW2178470/CW2178470/ws.xml -rw---- 2.0 fat 308 bl defN 2004年8月15日 09:37 CW2178470/xsd/WSFolder.xsd -rw---- 2.0 fat 4897 bl defN 2004年8月15日 09:37 CW2178470/xsd/Task.xsd -rw---- 2.0 fat 770 bl defN 2004年8月15日 09:37 CW2178470/xsd/ContractWorkspace.xsd -rw---- 2.0 fat 4754 bl defN 2004年8月15日 09:37 CW2178470/xsd/AuditHistory.xsd -rw---- 2.0 fat 25564 bl defN 2004年8月15日 09:37 CW2178470/xsd/CommonTypes.xsd -rw---- 2.0 fat 5657 bl defN 2004年8月15日 09:37 CW2178470/xsd/MessageBoard.xsd -rw---- 2.0 fat 2471 bl defN 2004年8月15日 09:37 CW2178470/xsd/Plan.xsd -rw---- 2.0 fat 337 bl defN 2004年8月15日 09:37 CW2178470/xsd/InternalContractWorkspace.xsd -rw---- 2.0 fat 1045 bl defN 2004年8月15日 09:37 CW2178470/xsd/SalesContractRequest.xsd -rw---- 2.0 fat 3133 bl defN 2004年8月15日 09:37 CW2178470/xsd/FolderItem.xsd -rw---- 2.0 fat 906 bl defN 2004年8月15日 09:37 CW2178470/xsd/ContractRequest.xsd -rw---- 2.0 fat 8973 bl defN 2004年8月15日 09:37 CW2178470/xsd/WorkspaceTypes.xsd -rw---- 2.0 fat 4645 bl defN 2004年8月15日 09:37 CW2178470/xsd/Team.xsd -rw---- 2.0 fat 781 bl defN 2004年8月15日 09:37 CW2178470/xsd/SalesContractWorkspace.xsd 26ファイル、112005バイト非圧縮、21940バイト圧縮:80.4% (終了)
答え1
次のように使用できますunzip
。
unzip -j file[.zip] [file] [-x xfile]
ここでは、-j
ごみ箱のパスを表し、file[.zip]
はアーカイブ名、[file]
は処理するアーカイブメンバー、[-x xfile]
および処理から除外するアーカイブメンバーのリストです。これらのオプションはすべて、マニュアルページで詳しく説明されています。
したがって、あなたの場合は、次のように実行してください。
unzip -j ex1234.zip '*/*.csv' -x '*/*/*'
*.csv
深さレベル2に一致するアーカイブ内のすべてのファイルは、現在のディレクトリから抽出されます(パスが少なくとも2つ以上一致するため、ex1234.zip
深さレベル3以下のアーカイブメンバーを除く)。'*/*/*'
/
現在のディレクトリのすべてのアーカイブを処理するには、次のように実行できます。
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
オプションは省略可能そして、もし抽出するファイルは.csv
深さレベル1にあります(つまり、親ディレクトリはありません)。この場合、単に以下を実行できます。
for zipfile in *.zip; do unzip "$zipfile" '*.csv' -x '*/*'; done
答え2
Debian が提供する解凍を試してみてください。
UnZip 6.00 of 20 April 2009, by Debian. Original by Info-ZIP.
for file in ex*.zip
do
unzip -j $file '*.csv'
done
答え3
使うヒューズファイルシステムに基づくディレクトリツリーとしてzipファイルにアクセスします。各zipファイルをマウントし、cp
一般的な方法(シェルワイルドカード、コマンドなど)を使用してアクセスします。
そしてヒューズジッパー:
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
同じ方法を使用してください。archivemount
変えるfuse-zip
。
しかも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ではfusion-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
。
答え4
すべてのファイルがこのパターンと一致すると仮定すると、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
。