Jak mogę zmusić rozpakować / zip, aby nie tworzył podkatalogu, gdy go rozpakuję?

19

W zależności od sposobu utworzenia pliku zip, czasami wyodrębnia on wszystkie pliki bezpośrednio, a czasem wyodrębnia pliki do podkatalogu.

Jeśli to ostatnie jest prawdą, jak mogę zmusić unzippolecenie do „zignorowania” tego katalogu pierwszego poziomu?

Przykład:

cd /tmp
wget http://omeka.org/files/omeka-1.5.1.zip
mkdir omeka
unzip omeka-1.5.1.zip -d omeka/
cd omeka/
ll

Dostaję to /tmp/omeka/omeka-1.5.1/:

total 12
drwxr-xr-x 3 root root 4096 2012-05-08 18:44 ./
drwxrwxrwt 6 root root 4096 2012-05-08 18:44 ../
drwxr-xr-x 5 root root 4096 2012-04-20 14:54 omeka-1.5.1/

Chcę, aby pliki zostały wyodrębnione /tmp/omeka/(jeden poziom wyżej i brak struktury wersji w strukturze katalogów)

/tmp/omeka/(files)

Wiem, że mogę użyć -jopcji „śmieciowych ścieżek”, ale chcę zachować strukturę podkatalogów, a nie strukturę katalogów najwyższego poziomu. W jaki sposób mogę to zrobić?

cwd
źródło
ps: Wiem, że mogę wyodrębnić, a następnie mvpliki, ale chciałem sprawdzić, czy istnieje sposób, aby to zrobić od razu za pomocą polecenia unzip
cwd
Nie jestem tego świadomy. Ale jeśli nazwa pliku zawsze pasuje (oprócz rozszerzenia) do nazwy katalogu, całkiem łatwo jest skrypty zmienić nazwę wyodrębnionego katalogu.
Mat
3
Widzę, co próbujesz zrobić, ale nie poleciłbym tego. Usunięcie numeru wersji ze źródeł projektu to zły pomysł; powinieneś po prostu wypakować normalnie i użyć ln -s, jeśli chcesz mieć krótszą nazwę bez informacji o wersji. W ten sposób zawsze wiesz, jakiej wersji używasz i możesz łatwo zaktualizować do nowej wersji, przełączając łącze.
Burton Samograd,
@BurtonSamograd - byłoby idealnie, ale nadal jestem ciekawy, czy istnieje skuteczny sposób, aby to zrobić, ponieważ niektóre programy, na przykład Wordpress, umieszczają każdą wersję w /wordpress/katalogu (bez numeru wersji) w pliku zip. To jest rzeczywiście grzywny unzipi potem mv, ale nie mając kontrolę nad tym i mając to zrobić w dwóch etapach zawsze zdobyć na moje nerwy trochę. Na szczęście Wordpress również .tar.gz
smakuje
Spróbujcd /tmp/omeka && ln -s -T . omeka-1.5.1
James Youngman

Odpowiedzi:

4

Użyj systemu plików FUSE, który umożliwia przeglądanie archiwów takich jak katalogi, takie jak AVFS . Użyj, cpaby wyodrębnić pliki do wybranego katalogu.

mountavfs
cp -Rp ~/.avfs/tmp/omeka-1.5.1.zip\#/omeka-1.5.1 omeka

Ponieważ zakładamy, że w archiwum znajduje się jeden katalog najwyższego poziomu, możesz go skrócić

cp -Rp ~/.avfs/tmp/omeka-1.5.1.zip\#/* omeka
Gilles „SO- przestań być zły”
źródło
@ Giles, jesteś ekspertem, który przychodzi i odpowiada na wszystkie pytania, na które nikt inny nie może odpowiedzieć, więc sądzę, że to naprawdę jedyny sposób, aby to zrobić. Miałem nadzieję, unzipże mam na to trochę magii, jak na przykład określenie plików do wyodrębnienia */*, których mogę użyć bez instalowania innego narzędzia, ale chyba nie. Dzięki. +1
cwd
6

Jeśli plik zip nie zawiera struktury katalogów lub nie musisz go zachowywać, możesz użyć tego:

cd /tmp
wget http://omeka.org/files/omeka-1.5.1.zip
unzip -j omeka-1.5.1.zip -d omeka
cd omeka
ll
Eneko Alonso
źródło
3

Ten skrypt nie jest niezawodny, ale działa w prostych przypadkach:

...
dest=omeka
unzip omeka-1.5.1.zip -d $dest/

if [ `ls $dest | wc -l` == 1 ]; then
  subdir=`ls $dest`
  mv $dest/$subdir/* $dest/
  rmdir $dest/$subdir
fi

Sprawdza tylko, czy jest dokładnie jeden podkatalog, a jeśli tak, przenosi wszystko z niego, a następnie usuwa.

Steve Bennett
źródło
2

Właśnie się zarejestrowałem dzisiaj, więc nie mogę głosować za odpowiedzią @SteveBennet i nie mogę tam dodać komentarza.

Na podstawie jego odpowiedzi stworzyłem funkcję rekurencyjną:

...

shopt -s dotglob # To include hidden files in the move command

function moveSub {
  local dest=$1
  if [ `ls $dest | wc -l` == 1 ]; then
    local subdir=`ls $dest`
    moveSub "$dest/$subdir"
    mv $dest/$subdir/* $dest/
    rmdir $dest/$subdir
  fi
}

moveSub "$dest"

Tak jak powiedział @SteveBennet: ten skrypt nie jest niezawodny, ale działa w prostych przypadkach.

Mam nadzieję, że to się przyda.

Elysch
źródło
1

Potrzebujesz wygląda jak patch --strip=nopcja

Pożądane byłoby posiadanie opcji takiej jak patch --strip=number(lub -pnumber), która odcina numberkomponenty ścieżki na początku (zob. Porównywanie i scalanie plików: katalogi łatek ).

Inne rozwiązanie, zastosowanie

W przeciwnym razie istnieje inne rozwiązanie, trochę hackerskie, ale działa. W moim przypadku chciałem zastąpić katalog pełen istniejących plików zawartością zip, bez uprzedniego rozpakowania całego zip.

Gdy to rozwiązanie zadziała, a rozwiązanie @ Gilles będzie dostępne, to drugie również będzie działać. Jednak to rozwiązanie nie wymaga dostępności systemu plików FUSE.

Jak to zrobić

Zakładając, że znasz dodatkowy katalog, w twoim przypadku omeka-1.5.1możesz to zrobić:

mkdir omeka
ln -s . omeka/omeka-1.5.1 # create a symlink that redirects output
unzip omeka-1.5.1.zip -d omeka/
rm omeka/omeka-1.5.1 # remote symlink

unzipspróbuje rozpakować, do omeka-1.5.1którego w rzeczywistości jest dowiązanie symboliczne do zawierającego katalog. W rezultacie pliki trafią omekabezpośrednio.

Możliwe warianty

Możesz wyobrazić sobie warianty przekierowujące jedną lub więcej części hierarchii depeer.

ln -s ../myfoo omeka/omeka-1.5.1/foo
ln -s ../../mybarxyzzy omeka/omeka-1.5.1/subdir/bar

Wniosek

To rozwiązanie jest dość specyficzne, ale ma swoje przypadki użycia i właśnie z niego skorzystałem.

Stéphane Gourichon
źródło
Świetne rozwiązanie, jeśli znasz ścieżkę!
grepsedawk
Ścieżkę można sondować, wymieniając najpierw zawartość zip, np unzip -l. Za pomocą . Można to nawet zautomatyzować za pomocą skryptu, który określa część wspólnej ścieżki.
Stéphane Gourichon
Aha, o wiele łatwiej jest, jeśli znasz ścieżkę. Przez chwilę grałem z unzip -l, ale było trochę więcej grep / sed / awk, niż zamierzałem, więc się wycofałem.
grepsedawk
zipinfo -1może być dobry początek. Jaki jest twój przypadek użycia?
Stéphane Gourichon
github.com/grepsedawk/wow-config/blob/… w tym przypadku znam katalog :)
grepsedawk
1

Najprawdopodobniej chcesz uruchomić unzipz tą -jopcją, jak w:

unzip -j files.zip -d ./output/

Ale możesz być zaskoczony jego zachowaniem:

-j śmieciowe ścieżki. Struktura katalogów archiwum nie jest odtwarzana; wszystkie pliki są zdeponowane w katalogu wypakowywania (domyślnie bieżącym).

Jeśli wypakujesz files.zipdo katalogu wyjściowego, ./outputa otrzymasz:

./output/files/subfolder1/f1
./output/files/subfolder1/f2

wtedy -jopcja da ci to (wszystkie ścieżki w paski):

./output/f1
./output/f2
Vincenzo Pii
źródło