У мене є численні архіви zip, кожен з яких містить ряд архівів zip. Який найкращий спосіб рекурсивно витягувати всі файли, що містяться в цьому поштовому архіві та його дочірніх поштових архівах, які самі по собі не є поштовими архівами?
У мене є численні архіви zip, кожен з яких містить ряд архівів zip. Який найкращий спосіб рекурсивно витягувати всі файли, що містяться в цьому поштовому архіві та його дочірніх поштових архівах, які самі по собі не є поштовими архівами?
Відповіді:
Це дозволить витягнути всі поштові файли в поточний каталог, виключаючи поштові файли, що містяться в них.
find . -type f -name '*.zip' -exec unzip -- '{}' -x '*.zip' \;
Хоча це витягує вміст у поточний каталог, не всі файли в цьому каталозі будуть суворо потрапляти, оскільки вміст може містити підкаталоги.
Якщо ви дійсно хотіли, щоб усі файли були строго в поточному каталозі, ви можете запустити
find . -type f -mindepth 2 -exec mv -- '{}' . \;
Примітка. Це будуть файли клобіру, якщо в різних каталогах є два з однаковим іменем.
Якщо ви хочете рекурсивно витягувати всі zip-файли та зіпси, що містяться в ньому, наступне витягує всі поштові файли з поточного каталогу та всі цип-файли, що містяться в них, у поточний каталог.
while [ "`find . -type f -name '*.zip' | wc -l`" -gt 0 ]
do
find . -type f -name "*.zip" -exec unzip -- '{}' \; -exec rm -- '{}' \;
done
while [ "
знайти. -типу f -ім'я '*.? ar' | wc -l" -gt 0 ]; do find -type f -name "*.?ar" -exec mkdir -p '{}.dir' \; -exec unzip -d '{}.dir' -- '../{}' \; -exec rm -- '{}' \;; done
Наскільки я розумію, у вас є поштові архіви, які самі містять поштові архіви, і ви хочете розпаковувати вкладені блискавки щоразу, коли їх витягуєте.
Ось bash 4 скрипт, який розпаковує всі ZIP-файли в поточному каталозі та його підкаталогах рекурсивно, видаляє кожен zip-файл після його розпакування та продовжує тривати, поки є поштові файли. Файл zip у підкаталозі вилучається відносно цього підкаталогу. Попередження: протестовано, зробіть резервну копію оригінальних файлів, перш ніж випробувати її або замінити rm
, перемістивши zip-файл поза деревом каталогу .
shopt -s globstar nullglob
while set -- **/*.zip; [ $# -ge 1 ] do
for z; do
( cd -- "$(dirname "$z")" &&
z=${z##*/} &&
unzip -- "$z" &&
rm -- "$z"
)
done
done
Сценарій також буде працювати в zsh, якщо ви заміните shopt
рядок на setopt nullglob
.
Ось портативний еквівалент. Умова припинення є дещо складною, тому find
що спонтанно не повертає статус, щоб вказати, чи знайшов файли. Попередження: як зазначено вище.
while [ -n "$(find . -type f -name '*.zip' -exec sh -c '
cd "${z%/*}" &&
z=${z##*/} &&
unzip -- "$z" 1>&2 &&
rm -- "$z" &&
echo 1
')" ]; do :; done
unzip
цього не робити, тому що UNIX спосіб - це робити одне і робити це добре, а не обробляти всі божевільні особливі випадки у кожному інструменті. Таким чином, вам потрібно скористатися оболонкою (яка добре виконує завдання "зв'язати речі". Це робить його питанням програмування, і оскільки всі можливі питання програмування відповіли на StackOverflow, тут: Як ви рекурсивно розпаковуєте архіви в каталозі та його підкаталогах з командного рядка Unix?
Цей скрипт perl витягує кожен .zip файл у свій власний підкаталог. Запускайте сценарій не один раз для обробки вкладених zip-файлів. Він не видаляє .zip файли після вилучення, але ви можете внести ці зміни, додавши виклик unlink ().
#!/usr/bin/perl -w
# This script unzips all .zip files it finds in the current directory
# and all subdirectories. Contents are extracted into a subdirectory
# named after the zip file (eg. a.zip is extracted into a/).
# Run the script multiple times until all nested zip files are
# extracted. This is public domain software.
use strict;
use Cwd;
sub process_zip {
my $file = shift || die;
(my $dir = $file) =~ s,/[^/]+$,,;
(my $bare_file = $file);
$bare_file =~ s,.*/,,;
my $file_nopath = $bare_file;
$bare_file =~ s,\.zip$,,;
my $old_dir = getcwd();
chdir($dir) or die "Could not chdir from '$old_dir' to '$dir': $!";
if (-d $bare_file) {
chdir($old_dir);
# assume zip already extracted
return;
}
mkdir($bare_file);
chdir($bare_file);
system("unzip '../$file_nopath'");
chdir($old_dir);
}
my $cmd = "find . -name '*.zip'";
open(my $fh, "$cmd |") or die "Error running '$cmd': $!";
while(<$fh>) {
chomp;
process_zip($_);
}
Найпростіший спосіб - це використовувати atool: http://www.nongnu.org/atool/ Це дуже хороший сценарій, який використовує програми zip, unzip, tar, rar тощо для отримання будь-якого архіву.
Використовуйте atool -x package_name.zip
для розпакування їх усіх або, якщо ви хочете використовувати його в каталозі з багатьма поштовими файлами, використовуйте простий for
цикл:
for f in *; do atool -x $f; fi
(перед цим вам доведеться cd
потрапити в потрібний каталог із zip-файлами).
atool
Поведінка тут не суттєво відрізняється від розпакування, я б сказав, він не рекурсивно витягує ZIP-файли.
Ви хочете бути обережними, автоматично розпаковуючи поштові файли всередині zip-файлів:
http://research.swtch.com/2010/03/zip-files-all-way-down.html
Можна створити zip-файл, який видає zip-файл як вихід, який створює zip-файл як вихідний, і т. Д. І т.д. і т. Д. Тобто, ви можете зробити zip-файл, який є фіксованою маззю "розпакувати" програму.
Крім того, я, начебто, пригадую людей, які роблять zip-файли, які б "вибухнули", тобто дуже маленький zip-файл розпакував би багатогігабайт виводу. Це грань методу компресії.
Можливо, це допоможе (працювало для мене):
function unzipAll(){
# find and count archives
archLst=`find . -type f -name "*.*ar"`
archLstSize=`echo $archLst| awk 'END{print NF}'`
# while archives exists do extract loop
while [ "$archLstSize" -gt 0 ]; do
# extract and remove all archives (found on single iteration)
for x in $archLst; do
mv "${x}" "${x}_";
unzip "${x}_" -d "${x}" && rm "${x}_";
done; #EO for
# find and count archives
archLst=`find . -type f -name "*.*ar"`
archLstSize=`echo $archLst| awk 'END{print NF}'`
done #EO while
}
Мені потрібно було таке рішення, як Giles 'з 2010 року, за винятком того, що мені потрібно було зберегти структуру папок, а не розпакувати все до каталогу верхнього рівня. Ось мій погляд на його, додавши / змінивши три рядки:
#!/bin/bash
shopt -s globstar nullglob
while set -- **/*.zip; [ $# -ge 1 ]
do
for z
do
( cd -- "$(dirname "$z")" &&
z=${z##*/} &&
cp -- "$z" "$z".bak &&
mkdir -- "$z"dir &&
unzip -- "$z" -d "$z"dir &&
rm -- "$z"
)
done
done
Ознайомтеся з цією утилітою nzip на базі Java для вкладених zip-файлів. Витягування та стискання вкладених блискавок можна легко виконати за допомогою наступних команд
java -jar nzip.jar -c список -s readme.zip
java -jar nzip.jar -c витяг -s "C: \ project \ readme.zip" -t readme
java -jar nzip.jar -c компрес -s readme -t "C: \ project \ readme.zip"
PS. Я автор і буду радий швидко виправити будь-які помилки.