Finns det ett sätt att zippa alla filer i en viss katalog med kommandot zip
? Jag har hört talas om att använda *.*
, men jag vill också att den ska fungera för filer utan förlängning.
Kommentarer
Svar
Du kan bara använda *
; det finns inget behov för *.*
. Filtillägg är inte speciella på Unix. *
matchar noll eller mer ch tecken – inklusive en prick. Så det matchar foo.png
, eftersom det är noll eller fler tecken (sju, för att vara exakt).
Observera att *
matchar som standard inte filer som börjar med en punkt (inte heller *.*
). Detta är ofta vad du vill ha. Om inte, i bash, om du shopt -s dotglob
kommer det (men kommer fortfarande att utesluta .
och ..
). Andra skal har olika sätt (eller inget alls) att inkludera dotfiler.
Alternativt har zip
också en -r
(rekursivt) alternativ för att göra hela katalogträd på en gång (och inte behöva oroa sig för dotfile-problemet):
zip -r myfiles.zip mydir
där mydir
är den katalog som innehåller dina filer. Observera att den producerade zip-filen innehåller såväl katalogstrukturen som filerna. Som peterph påpekar i sin kommentar ses detta vanligtvis som en bra sak: att extrahera zip kommer att lagra alla extraherade filer i en underkatalog.
Du kan också be zip att inte spara sökvägarna med -j
/ --junk-paths
alternativet.
Kommandot zip
kommer med dokumentation som berättar om alla dess (många) alternativ; skriv man zip
för att se den dokumentationen. Detta är inte unikt för zip. Du kan få dokumentation för de flesta kommandon på detta sätt.
Kommentarer
- Du kanske vill lägga till att det är ansågs vara bra att innehålla allt i arkivet i en toppkatalog – så att man inte ’ t förorenar sin nuvarande katalog vid utvinning.
- @peterph klar. Även om detta är mindre en konvention i zip-filer än i t.ex. tarfiler är jag ’ rädd.
- tyvärr ja. Troligtvis på grund av fönstren dra av arv ’ n ’ släpp till skrivbordet och Linux-arvet att arbeta med källkoder.
- Håll in tänk på att
*
shell-globbing inte innehåller ’ t dotfiles (dvs. filnamn som börjar med.
). Detta är en annan fördel med att zippa hela katalogen med namn. - Men att använda -r inkluderar själva katalogen, som bryter vad jag ’ jag gör. Skulle ’ t * inkludera
.
och..
?
Svar
I mitt fall ville jag zip varje fil i sitt eget arkiv, så jag gjorde följande (i zsh
):
$ for file in *; do zip ${file%.*}.zip $file; done
Kommentarer
- Där ’ nej
mkv
här? Inget här är inte särskiltzsh
-specifikt. Du ’ Du vill citera alla variabler som innehåller ett filnamn korrekt, såzip "${file%.*}.zip" "$file"
med dubbla citat runt båda variablerna. - @ tripleee Först och främst tack för att jag påpekade min felaktiga hänvisning till
mkv
. För det andra är det inte nödvändigt att citera argument izsh
, till skillnad frånbash
. Det är ’ varför jag specificerade att detta var ett kommando förzsh
. - Ersätter den sista semikolon med ett ampersand kan påskynda det avsevärt (om antalet filer i katalogen är rimligt …). Annars
find . -type f -maxdepth 1 -print0|xargs -r0 -n1 -P64 -I{} bash -c 'f="{}"; zip "${f%.*}.zip" "$f"'
(med-P
justerat beroende på dina CPU-trådar …) (Många GNU-beroenden …) - för att zip varje fil i sitt eget arkiv, gör
gzip *
Svar
Ett annat sätt skulle vara att använda find och xargs: (detta kan inkludera en ”.” -katalog i zip-filen, men den ska ändå extraheras korrekt. Med mitt test strippade zip punkten innan komprimering) find . -type f -exec zip zipfile.zip {} +
(+
kan ersättas med \;
om din version av find
inte stöder +
slut för exec. Det kommer dock att gå långsammare …)
Detta inkluderar som standard alla underkataloger. På GNU kan -maxdepth
förhindra det.
Kommentarer
- (till skillnad från lösningarna som använder
*
, detta kommer att inkludera dotfiles och kommer inte att vinna ’ om det finns för många filer i en katalog)
Svar
En annan (långsam) metod för att göra detta (som lägger till en fil i zip-filen åt gången):
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
Detta har punktfilerna av *
(lösning tillagd) och skulle vara start-zip en gång för varje fil och lägga till den i arkivet. I bash
skulle det hantera en stor mängd filer.
Det skulle vara långsammare än de flesta andra metoder, men det är relativt enkelt.
Kommentarer
- Jag skulle säga att detta är mindre enkelt än det accepterade svaret och långsammare, vilket uppmanar frågan: ” Varför skulle någon göra detta? ”. Om du kan svara på den frågan rekommenderar jag att du lägger det sammanhanget i ditt svar, annars tycker jag att det är ett dåligt svar på en gammal fråga som redan har ett bra svar.
- @Centimane: Jag noterar begränsningarna . Jag tycker att detta har pedagogiskt värde. (Om du inte hoppar över kataloger är det ganska enkelt). Om du vill ha ett mycket snabbare svar med ett (standard) externt verktyg istället täcker mitt andra svar det. (med dotfiles-hanteringen borttagen (vilket påverkar korrektheten utan deras frånvaro som nämns i frågan), tycker jag att den är ganska elegant):
for f in *; do zip zip.zip "$f"; done
- Observera att det accepterade svaret ’ använder inte ett externt kommando och skulle vara snabbare. I vilket scenario skulle detta svar vara användbart?
- @Centimane Med tjära när det finns fler filer än vad bash kan skicka som parametrar. (hitta + xargs är bättre, för loopar är lättare …). Det är ett (unikt) svar på frågan. Det är verkligen inte det optimala svaret. (Icke optimala svar kan fortfarande vara användbara för liknande problem, om någon har en något annorlunda situation – t.ex. vill tjära filen någon katalog i den)
zip myarch.zip mydir/*
?zip -r myarch.zip mydir/*
zip -r myarch.zip mydir
*.*
betyder alla filer med en punkt. cp / m och dos alla filer hade en punkt, och det fick dig att skriva det (kunde inte göra*
). Därför kom människor för att se*.*
som alla filer. Så småningom lade Microsoft till långa filnamn som kan ha noll eller fler punkter. För att hitta en fil som har en prick i Windows måste du skriva*.*.*
.