我的要求的第一部分:
我想从 中提取单个文件ex1234.zip
。结构和内容ex1234.zip
:
ex1234 (directory)
directory1
ex1234 (directory)
directory2
ex1234.csv
我希望能够仅提取ex1234.csv
文件但不知道名称。
第二部分是能够对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 脂肪 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/audhistory.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匹配的所有文件ex1234.zip
(不包括深度级别 3 及以下的存档成员,因为'*/*/*'
路径至少匹配两个/
)。
现在,要处理当前目录中的所有档案,您可以运行:
for zipfile in *.zip; do unzip -j "$zipfile" '*/*.csv' -x '*/*/*'; done
.csv
它从当前目录中的每个存档中提取文件(这就是-j
需要的原因)。
在您的特定情况下,没有.csv
1 级深度,因此您也可以运行:
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 文件,然后使用正常方法(shell 通配符、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
如果您使用带有数组的 shell 以及在通配符不匹配时获取空列表的方法,则可以获得稍微更具可读性的脚本。例如,在 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
提取。