1

Я ищу чистый аналог командной строки для ark -ba <path> (в KDE) или file-roller -h <path> (в GNOME/Unity).

К сожалению, и ark, и file-roller требуют, чтобы X работал. Я знаю, что это относительно просто написать инструмент, который обнаруживает архивы на основе их расширения файла, а затем запускает соответствующую программу:

#!/bin/bash
if [[ -f "$1" ]] ; then
    case $1 in
        *.tar.bz2) tar xjvf $1 ;;
        *.tar.gz) tar xzvf $1 ;;
        *.bz2) bunzip2 $1 ;;
        *.rar) rar x $1 ;;
        *.gz) gunzip $1 ;;
        *.tar) tar xf $1 ;;
        *.tbz2) tar xjvf $1 ;;
        *.tgz) tar xzvf $1 ;;
        *.zip) unzip $1 ;;
        *.Z) uncompress $1 ;;
        *.7z) 7z x $1 ;;
        *) echo "'$1' cannot be extracted with this utility" ;;
    esac
else
    echo "path '$1' does not exist or is not a file"
fi

Однако, это не заботится об обнаружении подкаталогов (и фактически, многие программы извлечения даже не предоставляют такую опцию).

Так может ли быть программа, которая делает именно это?

2 ответа2

3

То, что вы описываете как "обнаружение подкаталогов", должно происходить по умолчанию. В этом примере с GNU tar:

$ tree
.
├── dir1
│   └── file4
├── dir2
│   ├── file5
│   └── file6
├── file1
├── file2
└── file3

Архив:

$ tar cvf all.tar *
$ mkdir new_dir
$ mv all.tar new_dir
$ cd new_dir
$ tar xvf all.tar
$ tree
.
├── all.tar
├── dir1
│   └── file4
├── dir2
│   ├── file5
│   └── file6
├── file1
├── file2
└── file3

Если вы используете архивную программу, которая не сохраняет структуру каталогов при создании архива (кстати, вы уверены в этом? Я не знаю никого, кто этого не делает), тогда информация теряется. Невозможно воссоздать структуру каталогов, если она не была сохранена в самом архиве, и в этом случае она должна быть воссоздана после извлечения архива по умолчанию.


Если вы хотите имитировать поведение ark -a:

  -a, --autosubfolder            Archive contents will be read, and if detected
                                 to not be a single folder archive, a subfolder
                                 with the name of the archive will be created.

Вы можете создать скрипт-обертку, который извлекает архив во временный каталог, затем, если временный каталог содержит только один другой каталог, переместите этот каталог в текущий рабочий каталог и удалите каталог tmp и, если в папке несколько файлов / каталогов. temp dir, переименуйте его в название архива. Что-то вроде этого:

#!/usr/bin/env bash

for file in "$@"
do
    ## Get the file's extension
    ext=${file##*.}
    ## Special case for compressed tar files. They sometimes
    ## have extensions like tar.bz2 or tar.gz etc.
    if [[ "$(basename "$file" ."$ext")" =~ \.tar$ ]]; then
                if [[ "$ext" = "gz" ]]; then
                        ext="tgz"
                elif [[ "$ext" = "bz2" ]]; then
                        ext="tbz"
                fi
        fi


        ## Create the temp dir
        tmpDir=$(mktemp -d XXXXXX);
    case $ext in
        7z)
            7z -o "$tmpDir" e "$file" 
            ;;
        tar)
            tar xf "$file" -C "$tmpDir" 
            ;;
                tbz)
                        tar xjf "$file" -C "$tmpDir" 
                        ;;

                tgz)
                        tar xzf "$file" -C "$tmpDir" 
                        ;;

        rar)
                        unrar e "$file" "$tmpDir"
            ;;
        zip)
            unzip "$file" -d "$tmpDir"
            ;;
        *)
            echo "Unknown extension: '$ext', skipping..."
            ;;
    esac

        ## Get the tmp dir's structure
        tmpContents=( "$tmpDir"/* )
        c=1
        ## If the tmpDir contains only one item and that is a directory
        if [[ ${#tmpContents[@]} = 1 ]] && [[ -d "${tmpContents[0]}" ]]
        then
                ## Move that directory to the current working directory
                ## and delete the tmpDir, renaming it if a file/directory with
                ## the same name already exists.
                dirName=${tmpContents[0]##*/}
                [[ -e "$dirName" ]] && dirName="$dirName.$c"
                while [[ -e "$dirName" ]]; do
                        ((c++))
                        dirName="${dirName/.*}.$c"
                done
                mv "${tmpContents[0]}" "$dirName"
        else
                ## If the tmpDir contains anything more than a single directory,
                ## rename thye tmpDir to the name of the archive sans extension.
                ## If a file/dir of that name already exists, add a counter.
                dirName="${file##*/}"     ## strip path
                dirName="${dirName%%.*}"  ## strip extension(s)
                [[ -e "$dirName" ]] && dirName="$dirName.$c"
                while [[ -e "$dirName" ]]; do
                        ((c++))
                        dirName="${dirName/.*}.$c"
                done
                mv "$tmpDir" "$dirName"
        fi
printf "Archive '%s' extracted to %s\n" "$file" "$dirName" >&2
done
2

aunpack от atool делает это по умолчанию.

Использование: aunpack <archive file>

Доступно в большинстве дистрибутивов Linux.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .