Як я можу змусити unzip / zip не створювати підкаталог, коли я його витягую?


19

Залежно від того, як створено zip-файл, іноді він витягує всі файли безпосередньо, а іноді витягує файли у підкаталог.

Якщо остання вірна, як я можу змусити unzipкоманду "ігнорувати" цей каталог першого рівня?

Приклад:

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

Що я отримую /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/

Мені потрібні файли, вилучені /tmp/omeka/((один рівень вгору і номер структури версії не включений в структуру каталогу)

/tmp/omeka/(files)

Я знаю, що можу використовувати -jпараметр для "небажаних шляхів", але хочу зберегти структуру підкаталогу, тільки не структуру каталогів верхнього рівня. Як я можу це зробити?


ps: Я знаю, що я можу витягнути, а потім mvфайли, але хотів дізнатися, чи є спосіб зробити це прямо з команди "unzip"
cwd

Мені про це не відомо. Але якщо ім'я файлу завжди збігається (крім розширення), ім'я каталогів, то сценарій перейменування вилученого режиму досить просто.
Мат

3
Я бачу, що ви намагаєтесь зробити, але я б не рекомендував це. Зняття номера версії з джерел проекту - погана ідея; вам слід просто витягти нормально і використовувати ln -s, якщо ви хочете коротше ім'я без інформації про версію. Таким чином, ви завжди знаєте, яку версію запущено, і можете легко оновити її до нової версії, перемикаючи посилання.
Бертон Самоград

@BurtonSamograd - це було б ідеально, але мені все одно цікаво, якщо є ефективний спосіб це зробити, тому що якесь програмне забезпечення, наприклад, Wordpress, є прикладом кожної версії всередині /wordpress/каталогу (без номера версії) всередині zip-файлу. Це дійсно чудово , unzipа потім , mvале не маючи ніякого контролю над цим і , щоб зробити це в два етапи завжди отримували на мої нерви мало. На щастя, Wordpress також входить у .tar.gzсмак :)
cwd

Спробуйтеcd /tmp/omeka && ln -s -T . omeka-1.5.1
Джеймс Янгмен

Відповіді:


4

Використовуйте файлову систему FUSE, яка дозволяє переглядати архіви на зразок каталогів, таких як AVFS . Використовуйте cpдля вилучення файлів у вибраний каталог.

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

Оскільки ми припускаємо, що в архіві є одна директорія верхнього рівня, ви можете її скоротити до

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

@Giles, ви експерт, який приходить і відповідає на всі питання, на які ніхто інший не може відповісти, тож я думаю, що це справді єдиний спосіб зробити це. Я сподівався, unzipщо це зробить якась магія, наприклад, вказати файли, які потрібно витягнути */*, якими я можу користуватися, не встановлюючи іншу утиліту, але, мабуть, ні. Спасибі. +1
cwd

6

Якщо ваш zip-файл не містить структури каталогів або вам не потрібно його зберігати, ви можете скористатися цим:

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

Цей сценарій не є надійним, але працює в простих випадках:

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

Він просто перевіряє, чи існує точно один підкаталог, і якщо так, переміщує все з нього, а потім видаляє.


2

Я щойно зареєструвався сьогодні, тому не можу відповісти на @SteveBennet відповідь і не можу додати коментар туди.

На основі його відповіді я створив рекурсивну функцію на зразок цієї:

...

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"

Так само, як сказав @SteveBennet: цей скрипт не є надійним, але працює в простих випадках.

Сподіваюся, що це корисно.


1

Потрібен виглядає patch --strip=nваріант

Хочеться мати варіант на зразок patch --strip=number(або -pnumber), який перетинає numberкомпоненти контуру на початку (посилання Порівняння та об’єднання файлів: папки каталогів ).

Інше рішення, застосовність

Якщо цього не зробити, є ще одне рішення, вид хакі, але працює. У моєму випадку я хотів перезаписати каталог, повний існуючих файлів із вмістом zip, не витягуючи спочатку повний zip.

Коли це рішення запрацює і рішення @ Жилса буде доступне, останнє також буде працювати. Але це рішення не вимагає наявності файлової системи FUSE.

Як це зробити

Припустимо, що ви знаєте додатковий каталог, у вашому випадку omeka-1.5.1ви можете це зробити:

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

unzipспробуємо розпакувати, до omeka-1.5.1чого насправді є посилання на вміст dir. В результаті файли потраплять omekaбезпосередньо.

Можливі варіанти

Ви можете уявити варіанти для перенаправлення однієї або декількох частин ієрархії залежних.

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

Висновок

Це рішення є дещо конкретним, але він має свої випадки використання, і я просто випадково його використовував.


Чудове рішення, якщо ви знаєте шлях!
grepsedawk

Шлях можна пробувати, описуючи спочатку zip-вміст, наприклад, з unzip -l. Це навіть може бути автоматизовано за допомогою сценарію, який визначає частину загального шляху.
Стефан Гурішон

О, тотально, просто тонну простіше, якщо ти знаєш шлях. Я грав з unzip -l трохи, але це було трохи більше grep / sed / awk, ніж я мав намір, тому я відступив.
grepsedawk

zipinfo -1може бути хорошим початком. Який ваш випадок використання?
Стефан Гурішон

github.com/grepsedawk/wow-config/blob/… в цьому випадку я знаю каталог :)
grepsedawk

1

Швидше за все, ви хочете запустити unzipцей -jпараметр, як у:

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

Але ви можете бути здивовані його поведінкою:

-j нездорові стежки. Структура каталогів архіву не відтворена; всі файли зберігаються в каталозі вилучення (за замовчуванням поточний).

Якщо ви витягуєте files.zipу вихідний каталог ./outputі ви отримуєте це в результаті:

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

то -jпараметр надасть вам це (усі шляхи смугасті):

./output/f1
./output/f2
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.