Come posso forzare decomprimere / zip per non creare una sottodirectory quando la estraggo?


19

A seconda di come viene creato un file zip, a volte estrarrà direttamente tutti i file e, a volte, estrarrà i file in una sottodirectory.

Se quest'ultimo è vero, come posso forzare il unzipcomando a "ignorare" quella directory di primo livello?

Esempio:

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

Quello che sto ricevendo è /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/

Quello che voglio è dei file estratti /tmp/omeka/, (un livello superiore e nessun numero di versione incluso nella struttura delle directory)

/tmp/omeka/(files)

So che posso usare l' -jopzione per "percorsi spazzatura" ma voglio mantenere la struttura della sottodirectory, non solo la struttura della directory di livello superiore. Come posso fare questo?


ps: sono consapevole che posso estrarre e quindi mvi file, ma volevo vedere se c'era un modo per farlo immediatamente dal comando unzip
cwd

Non ne sono consapevole. Ma se il nome del file corrisponde sempre (a parte l'estensione) al nome della directory, è abbastanza semplice scrivere il nome della directory estratta.
Mat

3
Vedo cosa stai cercando di fare, ma non lo consiglierei. Spogliare il numero di versione dalle fonti del progetto è una cattiva idea; dovresti semplicemente estrarre normalmente e usare un ln -s se vuoi un nome più corto senza informazioni sulla versione. In questo modo sai sempre quale versione stai utilizzando e puoi facilmente aggiornare a una nuova versione cambiando il collegamento.
Burton Samograd,

@BurtonSamograd - sarebbe l'ideale, ma sono ancora curioso di sapere se esiste un modo efficace per farlo perché alcuni software, come Wordpress, ad esempio, inseriscono tutte le versioni in una /wordpress/directory (nessun numero di versione) all'interno del file zip. Va bene così unzipe poi, mvma non avere alcun controllo su questo e doverlo fare in due passaggi mi ha sempre innervosito un po '. Fortunatamente anche Wordpress ha un .tar.gzsapore :)
Cwd

Provacd /tmp/omeka && ln -s -T . omeka-1.5.1
James Youngman,

Risposte:


4

Utilizzare un file system FUSE che consente di sfogliare archivi come directory, come AVFS . Utilizzare cpper estrarre i file nella directory di propria scelta.

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

Poiché supponiamo che nell'archivio sia presente un'unica directory di livello superiore, puoi accorciarla a

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

@Giles sei l'esperto che viene e risponde a tutte le domande a cui nessun altro può rispondere, quindi immagino che questo sia davvero l'unico modo per farlo. Speravo di unzipavere un po 'di magia per farlo, come specificare i file da estrarre */*, che avrei potuto usare senza installare un'altra utility, ma credo di no. Grazie. +1
Cwd

6

Se il file zip non contiene alcuna struttura di directory o non è necessario conservarlo, è possibile utilizzare questo:

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

3

Questo script non è robusto, ma funziona nei casi semplici:

...
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

Controlla solo se esiste esattamente una sottodirectory e, in tal caso, sposta tutto fuori da essa e poi la elimina.


2

Mi sono appena registrato oggi, quindi non posso votare la risposta di @SteveBennet e non posso aggiungere un commento lì.

Sulla base della sua risposta ho creato una funzione ricorsiva come questa:

...

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"

Proprio come ha detto @SteveBennet: questo script non è robusto, ma funziona nei casi semplici.

Spero sia utile.


1

Bisogno sembra patch --strip=nopzione

Sarebbe desiderabile avere un'opzione come patch --strip=number(o -pnumber) che taglia i numbercomponenti del percorso all'inizio (rif. Confronto e unione dei file: directory delle patch ).

Altra soluzione, applicabilità

In caso contrario, c'è un'altra soluzione, un po 'di hacker ma funziona. Nel mio caso, volevo sovrascrivere una directory piena di file esistenti con il contenuto di una zip, senza estrarre prima la zip completa.

Quando questa soluzione funziona e la soluzione di @ Gilles è disponibile, anche quest'ultima funzionerà. Tuttavia, questa soluzione non richiede la disponibilità di un filesystem FUSE.

Come farlo

Supponendo che tu conosca la directory extra, nel tuo caso omeka-1.5.1, puoi farlo:

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

unzipproverà a decomprimere il omeka-1.5.1quale è in realtà un link simbolico al contenuto di dir. Di conseguenza, i file atterreranno omekadirettamente.

Possibili varianti

Puoi immaginare varianti per reindirizzare una o più parti di una gerarchia più profonda.

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

Conclusione

Questa soluzione è in qualche modo specifica, ma ha i suoi casi d'uso e mi è capitato di usarla.


Ottima soluzione se conosci il percorso!
grepsedawk,

Il percorso può essere sondato elencando prima il contenuto zip, ad esempio con unzip -l. Questo potrebbe anche essere automatizzato usando uno script che risolve parte del percorso che è comune.
Stéphane Gourichon,

Oh, totalmente, è solo molto più facile se conosci il percorso. Ho giocato con unzip -l per un po 'ma era un po' più grep / sed / awk di quanto pensassi, quindi sono uscito.
grepsedawk,

zipinfo -1potrebbe essere un buon inizio. Qual è il tuo caso d'uso?
Stéphane Gourichon,

github.com/grepsedawk/wow-config/blob/… in questo caso, conosco la directory :)
grepsedawk il

1

Molto probabilmente si desidera eseguire unzipcon l' -jopzione, come in:

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

Ma potresti essere sorpreso dal suo comportamento:

-j percorsi spazzatura. La struttura delle directory dell'archivio non viene ricreata; tutti i file vengono depositati nella directory di estrazione (per impostazione predefinita, quella corrente).

Se si estrae files.zipnella directory di output ./outpute si ottiene questo come risultato:

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

quindi l' -jopzione ti darà questo (tutti i percorsi sono a strisce):

./output/f1
./output/f2
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.