Эквивалент tar-strip-components = 1 в unzip?

У меня есть сценарий, который извлекает tar.gz-файл в указанный подкаталог mysubfolder :

mkdir mysubfolder; tar --extract --file=sourcefile.tar.gz --strip-components=1 --directory=mysubfolder;

Есть ли эквивалентный способ сделать это с помощью zip-файла?

40 голосов | спросил frigg 12 WedEurope/Moscow2012-12-12T15:58:17+04:00Europe/Moscow12bEurope/MoscowWed, 12 Dec 2012 15:58:17 +0400 2012, 15:58:17

2 ответа


22

Как сказал Матиас, unzip не имеет такой опции, но однострочный скрипт bash может выполнить задание.

Проблема заключается в следующем: лучший подход зависит от расположения архива. Решение, которое предполагает , один из главных файлов верхнего уровня с ошибкой потерпит неудачу, если содержимое находится прямо в корне архива (подумайте о /a/foo /b/foo /foo и хаос зачистки /a и /b).

И тот же сбой происходит с tar --strip-component. Существует не одноразовое решение.

Итак, чтобы удалить корневой каталог dir, предположив, что есть один (и только ):

unzip -d "$dest" "$zip" && f=("$dest"/*) && mv "$dest"/*/* "$dest" && rmdir "${f[@]}"

Просто убедитесь, что файлы /dirs второго уровня not имеют одинаковое имя родителя верхнего уровня (например, /foo/foo). Но /foo/bar/foo и /foo/bar/bar в порядке. Если они это сделают или вы просто хотите быть в безопасности, вы можете использовать временную директорию для извлечения:

temp=$(mktemp -d) && unzip -d "$temp" "$zip" && mkdir -p "$dest" &&
mv "$temp"/*/* "$dest" && rmdir "$temp"/* "$temp"

Если вы используете Bash, вы можете проверить, является ли верхний уровень единственным каталогом или не используется:

f=("$temp"/*); (( ${#f[@]} == 1 )) && [[ -d "${f[0]}" ]] && echo "Single dir!"

Говоря о Bash, вы должны включить dotglob, чтобы включить скрытые файлы, и вы можете обернуть все в одну удобную функцию:

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"
)

Теперь поместите это в свой ~/.bashrc или ~/.profile, и вам больше не придется беспокоиться об этом. Просто используйте как:

unzip-strip sourcefile.zip mysubfolder

(обратите внимание, что он автоматически создаст mysubfolder для вас, если он не существует)

ответил MestreLion 28 MarpmThu, 28 Mar 2013 13:36:16 +04002013-03-28T13:36:16+04:0001 2013, 13:36:16
2

Я не мог найти такой вариант в страницах руководства для unzip , поэтому я боюсь, что это невозможно. : (

Однако (в зависимости от ситуации) вы можете обойти это. Например, если вы уверены, что единственный каталог верхнего уровня в zip-файле называется foo-, за которым следует номер версии, вы можете сделайте что-нибудь вроде этого:

cd /tmp
unzip /path/to/file.zip
cd foo-*
cp -r . /path/to/destination/folder
ответил Mathias Bynens 13 ThuEurope/Moscow2012-12-13T15:50:54+04:00Europe/Moscow12bEurope/MoscowThu, 13 Dec 2012 15:50:54 +0400 2012, 15:50:54

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132