Existuje způsob, jak pomocí příkazu zip
komprimovat všechny soubory v daném adresáři? Slyšel jsem o používání *.*
, ale chci, aby to fungovalo i pro soubory bez přípony.
Komentáře
Odpověď
Stačí použít *
; není třeba pro *.*
. Přípony souborů nejsou v Unixu speciální. *
odpovídá nule nebo více ch přízraky – včetně tečky. Odpovídá tedy foo.png
, protože to má nula nebo více znaků (přesněji sedm).
Všimněte si, že *
ve výchozím nastavení neodpovídá souborům začínajícím tečkou (*.*
). To je často to, co chcete. Pokud ne, v bash, pokud shopt -s dotglob
to uděláte (ale stále bude vylučovat .
a ..
). Jiné skořápky mají různé způsoby (nebo vůbec žádné) zahrnutí dotfile.
Alternativně zip
má také -r
(rekurzivní) možnost dělat celé adresářové stromy najednou (a nemusíte se starat o problém s dotfile):
zip -r myfiles.zip mydir
kde mydir
je adresář obsahující vaše soubory. Všimněte si, že vytvořený zip bude obsahovat adresářovou strukturu i soubory. Jak Peter poznamenává ve svém komentáři, obvykle je to považováno za dobrou věc: extrahování zipu úhledně uloží všechny extrahované soubory do jednoho podadresáře.
Můžete také říct zipu, aby neukládal cesty s -j
/ --junk-paths
možnost.
Příkaz zip
je dodáván s dokumentace, která vás informuje o všech jejích (mnoha) možnostech; zadejte man zip
a podívejte se na tuto dokumentaci. Toto není jedinečné pro zip; dokumentaci pro většinu příkazů získáte tímto způsobem.
Komentáře
- Možná budete chtít přidat, že je považováno za osvědčený postup obsahovat vše v archivu v adresáři nejvyšší úrovně – aby neznečisťoval ‚ jeho aktuální adresář extrakcí.
- @peterph hotovo. I když se jedná o menší konvenci v zip souborech než např. v tarfile, bojím se ‚.
- bohužel ano. Pravděpodobně kvůli oknům dědictví drag ‚ n ‚ přejít na plochu a linuxové dědictví práce se zdrojovými kódy.
- Ponechat pamatujte, že
*
shell globbing neobsahuje ‚ t dotfiles (tj. názvy souborů začínající.
). To je další výhoda zipování celého adresáře podle názvu. - Ale použití -r zahrnuje samotný adresář, který rozbíjí to, co jsem ‚ dělám. Nebyl by ‚ t * zahrnut
.
a..
?
Odpověď
V mém případě jsem chtěl zazipovat každý soubor do vlastního archivu, takže jsem udělal následující (v zsh
):
$ for file in *; do zip ${file%.*}.zip $file; done
Komentáře
- Tam ‚ s ne
mkv
zde? Také zde nic není zvlášťzsh
-specifické. ‚ Budete chtít řádně citovat jakoukoli proměnnou obsahující název souboru, takžezip "${file%.*}.zip" "$file"
uvést uvozovky kolem obou proměnných. - @tripleee Za prvé, děkuji za poukázání na můj chybný odkaz na
mkv
. Zadruhé, citování argumentů je vzsh
zbytečné, na rozdíl odbash
. Proto jsem ‚ uvedl, že se jedná o příkaz prozsh
. - Výměna posledního středníku za ampersand by to mohl výrazně zrychlit (pokud je počet souborů v adresáři přiměřený …). Jinak
find . -type f -maxdepth 1 -print0|xargs -r0 -n1 -P64 -I{} bash -c 'f="{}"; zip "${f%.*}.zip" "$f"'
(s úpravou-P
v závislosti na vašich vláknech CPU …) (Mnoho závislostí GNU …) - Chcete-li každý soubor zazipovat do vlastního archivu, proveďte
gzip *
odpověď
Jiným způsobem by bylo použití find a xargs: (to může zahrnovat adresář „.“ v zipu, ale stále by se měl správně extrahovat. S mým testem zip před tím odstranil tečku komprese) find . -type f -exec zip zipfile.zip {} +
(+
lze nahradit \;
pokud vaše verze find
nepodporuje konec +
pro exec. Bude to ale pomalejší …)
Ve výchozím nastavení budou zahrnuty všechny podadresáře. Na GNU tomu může -maxdepth
zabránit.
Komentáře
- (na rozdíl od řešení využívajících
*
, bude to zahrnovat dotfiles a ‚ nepřekročí, pokud je v adresáři příliš mnoho souborů)
Odpovědět
Další (pomalá) metoda, jak toho dosáhnout (která přidává do zipu po jednom souboru):
for f in * .[^.]*; do [ -r "$f" ] || continue # Skip directories or non-existant files (Probably ".[^.]*" if directory has no dotfiles). Using -e will allow directories to be used as well zip zipfile.zip "$f" # If directories are included, you probably want to add -r done
Toto má problémy se souborem dotfile *
(přidáno řešení) a pro každý soubor by se spustil zip jednou, což by jej přidalo do archivu. V bash
by se zabýval velkým množstvím souborů.
Bylo by to pomalejší než u většiny ostatních metod, ale je to relativně jednoduché.
Komentáře
- Řekl bych, že je to méně jednoduché než přijatá odpověď a pomalejší, což vyvolává otázku: “ Proč by to někdo dělal? „. Pokud na tuto otázku můžete odpovědět, doporučuji vám, abyste do své odpovědi vložili tento kontext, jinak si myslím, že je to špatná odpověď na starou otázku, která již má dobrou odpověď.
- @Centimane: Beru na vědomí omezení . Cítím, že to má vzdělávací hodnotu. (Pokud nepřeskočíte adresáře, je to docela jednoduché). Pokud chcete mnohem rychlejší odpověď pomocí (standardního) externího nástroje, moje další odpověď pokrývá to. (s odstraněnou manipulací s dotfiles (což ovlivňuje správnost bez jejich nepřítomnosti zmíněné v otázce) mám pocit, že je to celkem elegantní):
for f in *; do zip zip.zip "$f"; done
- Všimněte si, že přijatý odpověď nepoužívá ‚ t externí příkaz a byla by rychlejší. V jakém scénáři by byla tato odpověď užitečná?
- @Centimane With tar when there are more files than what bash can pass as parameters. (find + xargs jsou lepší, protože smyčky jsou jednodušší …). Je to (jedinečná) odpověď na otázku. Určitě to není optimální odpověď. (Neoptimální odpovědi mohou být stále užitečné pro podobné problémy, pokud má někdo trochu jinou situaci – např. Chce, aby soubor tar obsahoval nějaké adresáře)
zip myarch.zip mydir/*
?zip -r myarch.zip mydir/*
zip -r myarch.zip mydir
*.*
znamená jakýkoli soubor s tečkou. cp / ma dos všechny soubory měly tečku a vy jste je museli psát (nemohlo to*
). Lidé se proto přišli podívat*.*
jako všechny soubory. Microsoft nakonec přidal názvy dlouhých souborů, které by mohly mít nulu nebo více teček. Chcete-li najít soubor, který má tečku v systému Windows, musíte zadat*.*.*
.