Czy istnieje sposób na spakowanie wszystkich plików w danym katalogu za pomocą polecenia zip
? Słyszałem o używaniu *.*
, ale chcę, aby działało też z plikami bez rozszerzeń.
Komentarze
Odpowiedź
Możesz po prostu użyć *
; nie ma potrzeby dla *.*
. Rozszerzenia plików nie są specjalne w systemie Unix. *
dopasowuje zero lub więcej znaków znaki – w tym kropka. Więc pasuje do foo.png
, ponieważ to „zero lub więcej znaków (dokładnie siedem).
Zwróć uwagę, że *
domyślnie nie „t dopasowuje plików zaczynających się kropką (podobnie *.*
). Często tego chcesz. Jeśli nie, w bash, jeśli shopt -s dotglob
będzie to (ale nadal będzie wykluczone .
i ..
). Inne powłoki mają różne sposoby dołączania plików dotfile (lub nie mają ich wcale).
Alternatywnie zip
ma również -r
(rekurencyjna) opcja wykonywania całych drzew katalogów naraz (bez martwienia się o problem z plikami dotfile):
zip -r myfiles.zip mydir
gdzie mydir
to katalog zawierający twoje pliki. Zwróć uwagę, że utworzony plik ZIP będzie zawierał strukturę katalogów, a także pliki. Jak zauważył peterph w swoim komentarzu, jest to zwykle postrzegane jako dobra rzecz: wypakowanie pliku zip będzie starannie przechowywać wszystkie rozpakowane pliki w jednym podkatalogu.
Możesz również nakazać zipowi, aby nie zapisywał ścieżek z Opcja -j
/ --junk-paths
.
Polecenie zip
zawiera dokumentacja informująca o wszystkich jego (wielu) opcjach; wpisz man zip
, aby zobaczyć tę dokumentację. To nie jest unikalne dla zip; w ten sposób możesz uzyskać dokumentację dla większości poleceń.
Komentarze
- Możesz dodać, że jest to za dobrą praktykę uważa się umieszczanie wszystkiego w archiwum w katalogu najwyższego poziomu – aby nie ' nie zanieczyszczać swojego bieżącego katalogu podczas rozpakowywania.
- @peterph gotowe. Chociaż jest to mniej konwencja w plikach zip niż np. w plikach tar, ' boję się.
- niestety tak. Prawdopodobnie z powodu okien dziedzictwo przeciągania ' n ' upuszczania na pulpit i linuxowe dziedzictwo pracy z kodami źródłowymi.
- Zachowaj pamiętaj, że
*
shell-globbing nie ' nie zawiera plików z kropkami (tj. nazw plików zaczynających się od.
). Jest to kolejna zaleta spakowania całego katalogu według nazwy. - Jednak użycie -r obejmuje sam katalog, co niszczy to, co ja ' robię. Czy nie ' t * obejmowałby
.
i..
?
Odpowiedź
W moim przypadku chciałem spakować każdy plik do jego własnego archiwum, więc zrobiłem co następuje (w zsh
):
$ for file in *; do zip ${file%.*}.zip $file; done
Komentarze
- Tam ' nie
mkv
tutaj? Również nic tutaj nie jest szczególniezsh
-specyficzne. ' Będziesz chciał poprawnie cytować każdą zmienną zawierającą nazwę pliku, więczip "${file%.*}.zip" "$file"
z podwójnymi cudzysłowami wokół obu zmiennych. - @tripleee Po pierwsze, dziękuję za wskazanie mojego błędnego odniesienia do
mkv
. Po drugie, cytowanie argumentów jest niepotrzebne wzsh
, w przeciwieństwie dobash
. Właśnie dlatego ' wskazałem, że jest to polecenie dlazsh
. - Zastąpienie ostatniego średnika znakiem znak ampersand może go znacznie przyspieszyć (jeśli liczba plików w katalogu jest rozsądna …). W przeciwnym razie
find . -type f -maxdepth 1 -print0|xargs -r0 -n1 -P64 -I{} bash -c 'f="{}"; zip "${f%.*}.zip" "$f"'
(z-P
dostosowanymi w zależności od wątków procesora …) (Wiele zależności GNU …) - aby spakować każdy plik do własnego archiwum, wykonaj
gzip *
Odpowiedz
Innym sposobem byłoby użycie funkcji find i xargs: (może to zawierać katalog „.” w pliku zip, ale nadal powinien zostać wyodrębniony poprawnie. W moim teście zip usunął kropkę przed kompresja) find . -type f -exec zip zipfile.zip {} +
(+
można zastąpić \;
jeśli Twoja wersja find
nie obsługuje zakończenia +
dla exec. Będzie jednak wolniejsze …)
Domyślnie obejmie to wszystkie podkatalogi. W GNU find -maxdepth
może temu zapobiec.
Komentarze
- (w przeciwieństwie do rozwiązań używających
*
, obejmie to pliki dotfiles i nie spowoduje ' przewrócenia, jeśli w katalogu jest za dużo plików)
Odpowiedź
Inna (wolna) metoda, aby to zrobić (która dodaje po jednym pliku do ZIP):
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
To ma problemy z dotfile *
(obejście zostało dodane) i zostanie uruchomione spakowanie raz dla każdego pliku, dodając go do archiwum. W bash
zajmowałoby się dużą ilością plików.
Byłoby wolniejsze niż większość innych metod, ale jest stosunkowo proste.
Komentarze
- Powiedziałbym, że jest to mniej proste niż zaakceptowana odpowiedź i wolniejsze, co prowadzi do pytania: ” Dlaczego ktoś miałby to zrobić? „. Jeśli możesz odpowiedzieć na to pytanie, radzę umieścić ten kontekst w swojej odpowiedzi, w przeciwnym razie uważam, że jest to zła odpowiedź na stare pytanie, na które już jest dobra odpowiedź.
- @Centimane: Zwracam uwagę na ograniczenia . Czuję, że ma to wartość edukacyjną. (Jeśli nie pomijasz katalogów, jest to dość proste). Jeśli chcesz uzyskać znacznie szybszą odpowiedź za pomocą (standardowego) narzędzia zewnętrznego, moja druga odpowiedź obejmuje to. (po usunięciu obsługi plików dotfiles (co wpływa na poprawność bez ich braku wspomnianego w pytaniu), wydaje mi się, że jest to całkiem eleganckie):
for f in *; do zip zip.zip "$f"; done
- Zauważ, że zaakceptowane odpowiedź nie ' nie używa zewnętrznego polecenia i działałaby szybciej. W jakim scenariuszu ta odpowiedź byłaby przydatna?
- @Centimane Z tar, gdy jest więcej plików niż to, co bash może przekazać jako parametry. (znajdź + xargs są lepsze, bo pętle są łatwiejsze …). To (wyjątkowa) odpowiedź na to pytanie. Z pewnością nie jest to optymalna odpowiedź. (Nieoptymalne odpowiedzi mogą nadal być przydatne w przypadku podobnych problemów, jeśli ktoś ma nieco inną sytuację – np. Chcąc plik tar z jakimikolwiek katalogami)
zip myarch.zip mydir/*
?zip -r myarch.zip mydir/*
zip -r myarch.zip mydir
*.*
oznacza dowolny plik z kropką. W cp / m i dos, wszystkie pliki miały kropkę i spowodowało to konieczność jej wpisania (nie można było tego zrobić*
). Dlatego ludzie przyszli zobaczyć*.*
jako wszystkie pliki. Ostatecznie Microsoft dodał długie nazwy plików, które mogły mieć zero lub więcej kropek. Aby znaleźć plik, który ma kropkę w oknach, musisz wpisać*.*.*
.