Risposte:
Come ha detto Mathias, unzip
non ha questa opzione, ma uno script bash da una riga può fare il lavoro.
Il problema è: l'approccio migliore dipende dal layout dell'archivio. Una soluzione che presuppone una singola directory di livello superiore fallirà miseramente se il contenuto si trova direttamente nella radice dell'archivio (pensare /a/foo
/b/foo
/foo
e il caos dello stripping /a
e /b
).
E lo stesso fallimento accade con tar --strip-component
. Non esiste una soluzione unica per tutti.
Quindi, per eliminare la directory principale, supponendo che ce ne sia una (e una sola):
unzip -d "$dest" "$zip" && f=("$dest"/*) && mv "$dest"/*/* "$dest" && rmdir "${f[@]}"
Assicurati solo che i file / le directory di secondo livello non abbiano lo stesso nome del genitore di primo livello (ad esempio /foo/foo
). Ma /foo/bar/foo
e /foo/bar/bar
sono ok. Se lo fanno, o vuoi solo essere al sicuro, puoi usare una directory temporanea per l'estrazione:
temp=$(mktemp -d) && unzip -d "$temp" "$zip" && mkdir -p "$dest" &&
mv "$temp"/*/* "$dest" && rmdir "$temp"/* "$temp"
Se stai usando Bash, puoi verificare se il livello più alto è una singola directory o non usi:
f=("$temp"/*); (( ${#f[@]} == 1 )) && [[ -d "${f[0]}" ]] && echo "Single dir!"
A proposito di Bash, dovresti accenderlo dotglob
per includere file nascosti e puoi avvolgere tutto in un'unica, utile funzione:
unzip-strip() (
local zip=$1
local dest=${2:-.}
local temp=$(mktemp -d) && unzip -d "$temp" "$zip" && mkdir -p "$dest" &&
shopt -s dotglob && local f=("$temp"/*) &&
if (( ${#f[@]} == 1 )) && [[ -d "${f[0]}" ]] ; then
mv "$temp"/*/* "$dest"
else
mv "$temp"/* "$dest"
fi && rmdir "$temp"/* "$temp"
)
Ora inseriscilo nel tuo ~/.bashrc
o ~/.profile
e non dovrai più preoccupartene. Usa semplicemente come:
unzip-strip sourcefile.zip mysubfolder
(nota che creerà automaticamente mysubfolder
per te se non esiste)
Non ho trovato un'opzione simile nelle pagine del manuale perunzip
, quindi temo che sia impossibile. :(
Tuttavia, (a seconda della situazione) potresti aggirare il problema. Ad esempio, se sei sicuro che l'unica directory di primo livello nel file zip sia denominata foo-
seguita da un numero di versione, potresti fare qualcosa del genere:
cd /tmp
unzip /path/to/file.zip
cd foo-*
cp -r . /path/to/destination/folder
rm -rf foo-*
apposta perché è potenzialmente pericoloso. E se esistesse già una cartella denominata foo-bar
? Si noti che l'estrazione viene eseguita all'interno della /tmp
cartella, che viene svuotata automaticamente di tanto in tanto.
&&
: un determinato passaggio si verifica solo se il passaggio precedente ha avuto esito positivo, quindi l'ultimo (il rm
) viene eseguito solo se tutti i passaggi sono stati completati senza errori.
/tmp/some-hardcoded-folder-name
una cartella temporanea, ma invece si dovrebbe usare mktemp
per questo: garantisce che non ci sarà tale cartella esistente. Controlla la mia risposta qui sotto.
È possibile utilizzare -j
per i percorsi spazzatura (non creare directory). Questo è consigliato solo per archivi a livello singolo piuttosto comuni. Gli archivi con strutture di directory multilivello verranno appiattiti - questo potrebbe persino portare a conflitti di nomi da estrarre per i file.
Dalla pagina man di decomprimere:
-j junk paths. The archive's directory structure is not recreated; all files are deposited in the extraction directory (by default, the current one).