You are not logged in.

#1 2022-05-03 04:13:41

random0
Member
Registered: 2022-04-07
Posts: 10

Why do archives have to be such a pain in Linux?

I always used Winrar in Windows, which gives you simple options like "Extract Here", "Extract each to separate folder" etc. Overall, really really easy and always works. All the archiving apps and built in functionalities I tried in Linux were bad IMO. They had weird things, errors, especially when dealing with .rar files, let alone multi-part ones and fully encrypted ones.

The point here is I want something that always works and perfectly handles bulk extractions / compresses. For example, Thunar's archive-plugin has some weird thing built in, called something along the lines of "smart extract", where files are put into their own folder if the archive has more than 1 direct child, but if the archive has a single folder as a direct child, then just that folder is extracted. This is a terrible idea because it is inconsistent when it comes to bulk processes, and those are the most important thing.

In any case, I had enough of the pre-existing programs and started writing my own scripts in python using modules like "zip", "unar" and "unrar". These scripts are supposed to be used for Thunar as custom actions, but maybe they can be ported to something else too? So far I finished the script that puts files into zips, and am close to completing the one that extracts files. I'd say, it's turning out fairly well, and exactly the way I wanted it to.

I'm thinking once I finish the extraction script, and potentially a script to browse file contents without extracting, i'd merge them into a single script and post it somewhere for other people. I've no idea where to be honest. I'm still new to linux, and even python, though I do have experience with coding.

Here is for example the zip script I finished earlier:
It is saved in "~/.config/Thunar/cust-scripts/" as "zip-files.py"
The custom action in thunar is called "Zip", it matches all patterns and files, and the command is:

gnome-terminal --title "ZIPPING FILES" -- python3 "$HOME/.config/Thunar/cust-scripts/zip-files.py" %d %N

Script:

# CALL SYNTAX: python3 "script name" "parent folder" "filename1" "filename2"...
# sys.argv[0] is the name of the script
# sys.argv[1] parent folder
# sys.argv[2:] the filenames

#########################################################

import os, sys, re, subprocess

#########################################################

NUM_FILES = None;
BASE_DIR = None
ZIP_OUTPUT_METHOD = None;
SINGLE_ZIP_NAME_TEMP = None
DUPE_ACTION = None;
FILENAMES_DICT = {}; # {"zipname1":["file1", "file2" ...], "zipname2":[]...}
PASSWORD = None
ERRORS = ""

#########################################################

def run():
    init()
    zip_output_method_user_input()
    if ZIP_OUTPUT_METHOD == "single": set_temp_name_for_signle_zip()
    build_filenames_dict_and_dupe_action()
    zip_password_user_input()
    zip_files()
    display_errors()

#########################################################

def init():
    global NUM_FILES, BASE_DIR

    NUM_FILES = len(sys.argv) - 2
    if NUM_FILES <= 0: input("Not enough arguments provided. Press Enter to exit."); quit()

    BASE_DIR = sys.argv[1].strip()
    if BASE_DIR.endswith("/"): BASE_DIR = BASE_DIR[:-1]

    if not os.access(BASE_DIR, os.W_OK): input("Write permission missing. Press Enter to exit."); quit()

#########################################################

def zip_output_method_user_input():
    global ZIP_OUTPUT_METHOD

    if NUM_FILES == 1:
        ZIP_OUTPUT_METHOD = "single"
    else:
        while 1==1:
            userInput = input("PUT FILES:\n(1) In a single zip file [default]\n(2) Each in a separate zip\n").strip()
            os.system("clear")
            if userInput == "1" or userInput == "": ZIP_OUTPUT_METHOD = "single"; break
            elif userInput == "2": ZIP_OUTPUT_METHOD = "separate"; break
            else: print("*** Invalid input. Try again.")

#########################################################

# the name is either the name of the file (without extension) or user is asked to provide one if multiple files to a signle zip
# the reason why this is temp is because if there already is such a zip, later the user will be asked for dupe action, and the name might be changed
def set_temp_name_for_signle_zip():
    global SINGLE_ZIP_NAME_TEMP
    if NUM_FILES == 1: SINGLE_ZIP_NAME_TEMP = sys.argv[2]
    else: SINGLE_ZIP_NAME_TEMP = get_single_zip_name_user_input()

def get_single_zip_name_user_input():
    while 1==1:
        userInput = input("NAME OF ZIP FILE (no extension) (can't contain: <>:\"/\?):\n").strip()
        os.system("clear")
        if re.match(r"^.*(<|>|:|\"|\/|\\|\||\?).*$", userInput) or userInput == "": print("*** Invalid name. Try again.")
        else: return userInput
    
#########################################################

# Populates the FILENAMES_DICT and asks for duplicate action if needed
def build_filenames_dict_and_dupe_action():
    global DUPE_ACTION, FILENAMES_DICT

    if ZIP_OUTPUT_METHOD == "single":
        finalSingleZipName = ""
        if os.path.exists(f"{BASE_DIR}/{SINGLE_ZIP_NAME_TEMP}.zip"):
            if not DUPE_ACTION: DUPE_ACTION = get_dupe_action_user_input()
            finalSingleZipName = exec_dupe_action(SINGLE_ZIP_NAME_TEMP)
        else: finalSingleZipName = SINGLE_ZIP_NAME_TEMP
        FILENAMES_DICT[f"{finalSingleZipName}.zip"] = [sys.argv[2]] if NUM_FILES == 1 else sys.argv[2:]

    elif ZIP_OUTPUT_METHOD == "separate":
        for fileName in sys.argv[2:]:
            dynamicZipName = f"{fileName}"
            finalZipName = ""
            if os.path.exists(f"{BASE_DIR}/{dynamicZipName}.zip"):
                if not DUPE_ACTION: DUPE_ACTION = get_dupe_action_user_input()
                finalZipName = exec_dupe_action(dynamicZipName)
            else: finalZipName = dynamicZipName
            if not finalZipName: continue
            FILENAMES_DICT[f"{finalZipName}.zip"] = [fileName]


def get_dupe_action_user_input():
    while 1==1:
        userInput = input("DUPLICATE ZIP/s FOUND. ACTION TO TAKE:\n(1) Skip [default]\n(2) Rename\n(3) Replace\n").strip()
        os.system("clear")
        if userInput == "1" or userInput == "": return "skip"
        elif userInput == "2": return "rename"
        elif userInput == "3": return "replace"
        else: print("*** Invalid input. Try again.")

# executes the dupe action and returns the zipName. "None" if "skip", same name if "replace", valid changed name if "rename"
def exec_dupe_action(zipName):
    if DUPE_ACTION == "skip":
        if ZIP_OUTPUT_METHOD == "single": quit()
        else: return None
    elif DUPE_ACTION == "replace":
        os.system(f"rm \"{BASE_DIR}/{zipName}.zip\"")
        return zipName
    else:
        counter = 1
        while 1==1:
            if not os.path.exists(f"{BASE_DIR}/{zipName} ({counter}).zip"): return f"{zipName} ({counter})"
            counter += 1

#########################################################

def zip_password_user_input():
    global PASSWORD
    userInput = input("ENTER PASSWORD TO USE (or leave empty)").strip()
    os.system("clear")
    PASSWORD = userInput
    
#########################################################

def zip_files():
    global ERRORS

    os.chdir(BASE_DIR)

    # zipName = the key
    zipFileCounter = 1
    for zipName in FILENAMES_DICT:
        validatedFileNamesStr = "" # no comas, each in double quotes
        for fileName in FILENAMES_DICT[zipName]:
            if os.path.exists(f"{BASE_DIR}/{fileName}"): validatedFileNamesStr += f"\"{fileName}\" "
            else: ERRORS += f"{fileName}\nFile was removed before having been zipped"

        validatedFileNamesStr = validatedFileNamesStr.strip()
        if validatedFileNamesStr == "": continue
        
        os.system("clear")
        if ZIP_OUTPUT_METHOD == "single": print(f"Adding files to {zipName}...")
        elif ZIP_OUTPUT_METHOD == "separate": print(f"Working on zip file {zipFileCounter}/{len(FILENAMES_DICT)}...")
        
        commandOutput = None
        if PASSWORD: commandOutput = subprocess.run(f"zip -q -r --password \"{PASSWORD}\" \"{zipName}\" {validatedFileNamesStr}", shell=True, text=True, capture_output=True)
        else: commandOutput = subprocess.run(f"zip -q -r \"{zipName}\" {validatedFileNamesStr}", shell=True, text=True, capture_output=True)
        
        if commandOutput.stdout.strip() != "": ERRORS += f"*** {zipName}:\n{commandOutput.stdout}\n\n" # for some reason zip outputs errors in stdout instead of stderr
        zipFileCounter += 1

#########################################################

def display_errors():
    global ERRORS
    os.system("clear")
    ERRORS = ERRORS.strip()
    if ERRORS == "": return
    print(f"OPERATION COMPLETE WITH ERRORS:\n\n{ERRORS}\n\n")
    input("Press any key and click enter to close")

run()

Also, I just finished the extractions script. I tested it and it works, but haven't used it much yet, or tested thoroughly. If anyone wants to test these, go ahead.
For the extraction script:
It is saved in "~/.config/Thunar/cust-scripts/" as "extract.py"
Two custom actions: "Extract Inner" and "Extract Outer"
Both match "Other files" with the pattern: *.rar;*.zip;*.7z;*.tar.gz;*.tar.bz2;*.zipx

Command for Exrtact Inner:

gnome-terminal --title "EXTRACTING IN: %d" -- python3 "$HOME/.config/Thunar/cust-scripts/extract.py" "inner" %F

Command for Exrtact Outer:

gnome-terminal --title "EXTRACTING IN: %d" -- python3 "$HOME/.config/Thunar/cust-scripts/extract.py" "outer" %F

Code:

# CALL SYNTAX: python3 "script name" "dir structure" "filepath1" "filepath2"...
# sys.argv[0] is the name of the script
# sys.argv[1] the dir structure: "inner"/"outer"
# sys.argv[2:] the filepaths

# Unar is used to handle everything except ".rar" files. Unrar handles ".rar" files exclusevly
    # When a password protected file is extracted with a wrong password, both modules create 0 bite files
    # This affects duplicate action and can mess things up.
    # That is why, each archive is extracted in a temp folder, and the temp folder is emptied after every extraction

#########################################################

import os, sys, re, subprocess

#########################################################
# GLOBALS

NUM_FILES = None
DIR_STRUCTURE = None
PARENT_FOLDER = None
TEMP_FOLDER = None
RM_TEMP_FOLDER_CONTENTS_COMMAND = None
MOVE_FILES_FROM_TEMP_COMMAND = None
RM_TEMP_FOLDER_COMMAND = None
FILE_PATHS_ARR = None
DUPE_ACTION = None
PASSWORD = None
BLOCK_EXTRACTION_TIME_PASSWORD_POPUPS = None
ERRORS = None

#########################################################
# RUN

def run():
    init()
    extraction_process()
    display_errors()
    
#########################################################
# MAIN

def init():
    global NUM_FILES, DIR_STRUCTURE, TEMP_FOLDER, RM_TEMP_FOLDER_CONTENTS_COMMAND, RM_TEMP_FOLDER_COMMAND, PARENT_FOLDER, FILE_PATHS_ARR, PASSWORD, BLOCK_EXTRACTION_TIME_PASSWORD_POPUPS, ERRORS
    
    NUM_FILES = len(sys.argv) - 2
    if NUM_FILES <= 0: input("Not enough arguments provided. Press Enter to exit."); quit()

    if sys.argv[1] == "inner" or sys.argv[1] == "outer": DIR_STRUCTURE = sys.argv[1]
    else: input("The dir structure argument is wrong. Press Enter to exit."); quit()

    PARENT_FOLDER = path_fixer(os.path.dirname(sys.argv[2]))
    if not os.access(PARENT_FOLDER, os.W_OK): input("Write permission missing. Press Enter to exit."); quit()

    TEMP_FOLDER = get_unused_path(f"{PARENT_FOLDER}/.tempExtract")
    os.system(f"mkdir \"{TEMP_FOLDER}\"")
    RM_TEMP_FOLDER_CONTENTS_COMMAND = f"rm -r \"{TEMP_FOLDER}/\"* > /dev/null 2>&1"
    RM_TEMP_FOLDER_COMMAND = f"rm -r \"{TEMP_FOLDER}\" > /dev/null 2>&1"

    move_command_generator()
    
    FILE_PATHS_ARR = []
    for filePath in sys.argv[2:]: FILE_PATHS_ARR.append(path_fixer(filePath))

    PASSWORD = "test"
    BLOCK_EXTRACTION_TIME_PASSWORD_POPUPS = False
    ERRORS = ""

def extraction_process():
    global ERRORS
    fileCounter = 1
    for filePath in FILE_PATHS_ARR:
        if not os.path.exists(filePath): ERRORS += f"{os.path.basename(filePath)}:\nFile removed before extraction\n\n"; continue
        if re.match(r"^.+\.part[0-9]+\.rar$", filePath) and not filePath.endswith("part1.rar"): continue
        single_archive_handler(filePath, fileCounter)
        fileCounter += 1   
    os.system(RM_TEMP_FOLDER_COMMAND)

def display_errors():
    global ERRORS
    os.system("clear")
    ERRORS = ERRORS.strip()
    if ERRORS == "": return
    print(f"OPERATION COMPLETE WITH ERRORS:\n\n{ERRORS}\n\n")
    input("Press enter to close")

#########################################################
# EXTRACTING SINGLE ARCHIVE

def single_archive_handler(filePath, fileCounter):
    global ERRORS

    while 1==1:
        os.system(RM_TEMP_FOLDER_CONTENTS_COMMAND)
        os.system("clear")
        print(f"EXTRACTING: {fileCounter}/{NUM_FILES}")
        
        extractCommand = extract_command_generator(filePath)
        extractCommandOutput = subprocess.run(extractCommand, shell=True, text=True, capture_output=True)
        
        errMsg = extractCommandOutput.stderr.strip()
        if errMsg:
            if is_wrong_pass_msg(errMsg):
                os.system(RM_TEMP_FOLDER_CONTENTS_COMMAND)
                errMsg = "Wrong password. Archive skipped."
                if get_wrong_pass_user_input(filePath) == "new pass entered": continue
            ERRORS += f"{os.path.basename(filePath)}:\n{errMsg}\n\n"

        if dupes_found(TEMP_FOLDER) and not DUPE_ACTION:
            dupe_action_user_input()
            move_command_generator()

        os.system(MOVE_FILES_FROM_TEMP_COMMAND)
        break

#########################################################
# COMMAND GENERATORS

def extract_command_generator(filePath):
    command = ""
    fileExt = filePath.split(".")[-1]
    isRar = True if fileExt == "rar" else False
    outputDir = get_outer_output_folder_unrar(filePath) if isRar and DIR_STRUCTURE == "outer" else TEMP_FOLDER

    if isRar:
        command = f"unrar x -op\"{outputDir}\" -p\"{PASSWORD}\" \"{filePath}\" > /dev/null" # unrar doesnt have a quite mode (I just need errors)
    else:
        unarInnerOuterFlag = "-force-directory" if DIR_STRUCTURE == "outer" else "-no-directory"
        command = f"unar -quiet -output-directory \"{outputDir}\" {unarInnerOuterFlag} -password \"{PASSWORD}\" \"{filePath}\""

    return command

def move_command_generator():
    global MOVE_FILES_FROM_TEMP_COMMAND

    command = "cp --recursive --link"
    if DUPE_ACTION == "skip": command += " --no-clobber"
    elif DUPE_ACTION == "rename": command += " --backup=numbered"
    elif DUPE_ACTION == "overwrite": command += " --force"
    command += f" \"{TEMP_FOLDER}/\"* \"{PARENT_FOLDER}/\" > /dev/null 2>&1"
    MOVE_FILES_FROM_TEMP_COMMAND = command
        
#########################################################
# USER INPUTS

def dupe_action_user_input():
    global DUPE_ACTION
    os.system("clear")
    while 1==1:
        userInput = input("DUPLICATES FOUND (this will apply to future duplicates):\n(1) Skip [default]\n(2) Rename\n(3) Overwrite\n").strip()
        os.system("clear")
        if userInput == "1" or userInput == "": DUPE_ACTION = "skip"; break
        elif userInput == "2": DUPE_ACTION = "rename"; break
        elif userInput == "3": DUPE_ACTION = "overwrite"; break
        else: print("*** Invalid input. Try again.")

def get_wrong_pass_user_input(filePath):
    global BLOCK_EXTRACTION_TIME_PASSWORD_POPUPS

    if BLOCK_EXTRACTION_TIME_PASSWORD_POPUPS: return "skip"

    os.system("clear")

    while 1==1:
        userInput = input(f"PASSWORD NEEDED FOR \"{os.path.basename(filePath)}\"\n(1) Enter password [default]\n(2) Skip archive\n(3) Skip all remaining\n").strip()
        os.system("clear")
        if userInput == "1" or userInput == "": password_user_input(); return "new pass entered"
        elif userInput == "2": return "skip"
        elif userInput == "3": BLOCK_EXTRACTION_TIME_PASSWORD_POPUPS = True; return "skip"
        else: print("*** Invalid input. Try again.")

def password_user_input():
    global PASSWORD
    os.system("clear")
    userInput = input("ENTER PASSWORD TO USE (or leave empty)\n").strip()
    os.system("clear")
    if userInput != "": PASSWORD = userInput

#########################################################
# GENERAL FUNCTIONS

# if the path provided ends with "/", it removes it
def path_fixer(filePath):
    if filePath.endswith("/"): filePath = filePath[:-1]
    return filePath

# given the path of a file/folder, it returns one that doesn't exist (numbered if original one exists)
def get_unused_path(filePath):
    if not os.path.exists(filePath): return filePath
    counter = 1
    while 1==1:
        newFilePath = f"{filePath} ({counter})"
        if not os.path.exists(newFilePath): return newFilePath
        counter += 1

# with unrar (for rar files), the outer functionality needs to be implemented by setting the output folder (to one with the archive's name)
def get_outer_output_folder_unrar(filePath):
    fileNameWoExt = os.path.basename(filePath)[:-4]
    if re.match(r"^.+\.part[0-9]+$", fileNameWoExt): fileNameWoExt = ".".join(fileNameWoExt.split(".")[:-1]) # remove .part
    return f"{TEMP_FOLDER}/{fileNameWoExt}"

# unrar and unar have different error messages, but with both, the first line of the error output contains "wrong password"
def is_wrong_pass_msg(errMsg):
    return True if "wrong password" in errMsg.split("\n")[0].strip() else False

# recursivly find duplicates (temp vs orig parent folder). Call using the TEMP FOLDER variable
def dupes_found(folderPath):
    dupes = False
    itemsInCurTempFolderArr = os.listdir(folderPath)
    for itemName in itemsInCurTempFolderArr:
        itemPath = f"{folderPath}/{itemName}"
        itemPathInParent = itemPath.replace(f"/{os.path.basename(TEMP_FOLDER)}", "")
        if os.path.isfile(itemPath) and os.path.exists(itemPathInParent): dupes = True
        elif os.path.isdir(itemPath): dupes = dupes_found(itemPath)
        if dupes == True: break
    return dupes
    
run()

Overall dependencies for this whole things are:
thunar, gnome-terminal, zip, unar, unrar and python

For the extraction script, you might want to call the custom action something else if you have thunar-archive-plugin installed, or remove the plugin.

Last edited by random0 (2022-05-05 08:42:33)

Offline

#2 2022-05-03 04:22:54

jasonwryan
Anarchist
From: .nz
Registered: 2009-05-09
Posts: 30,426
Website

Re: Why do archives have to be such a pain in Linux?

I've got by just fine using this for the last decade or so...

extract() {
  if [ -f $1 ] ; then
    case $1 in
       *.tar.bz2)   tar xvjf $1    ;;
       *.tar.gz)    tar xvzf $1    ;;
       *.tar.xz)    tar xvJf $1    ;;
       *.bz2)       bunzip2 $1     ;;
       *.rar)       unrar x $1     ;;
       *.gz)        gunzip $1      ;;
       *.tar)       tar xvf $1     ;;
       *.tbz2)      tar xvjf $1    ;;
       *.tgz)       tar xvzf $1    ;;
       *.zip)       unzip $1       ;;
       *.Z)         uncompress $1  ;;
       *.7z)        7z x $1        ;;
       *.xz)        unxz $1        ;;
       *.exe)       cabextract $1  ;;
       *)           echo "\`$1': unrecognized file compression" ;;
    esac
  else
    echo "\`$1' is not a valid file"
  fi

Arch + dwm   •   Mercurial repos  •   Surfraw

Registered Linux User #482438

Offline

#3 2022-05-03 04:39:26

random0
Member
Registered: 2022-04-07
Posts: 10

Re: Why do archives have to be such a pain in Linux?

Yeah but then the issue with having it like this is that you're relying on those modules' built in stuff to handle errors. The zip module for example displayed no error if a file was removed before having been zipped (only if during the zipping itself). I only expect errors from the module itself when strictly related to the archive structure etc. that i can't figure out myself. The rest should be handled manually, so that it's the same regardless of which module you're using and what type of file you're dealing with.

Especially with extracting, a simple loop and calling a "base" command again and again, it may ask you every time to enter a password, duplicate action etc., and I don't want that. I want to set it once, preferably during initiation, and not deal with it again.

Some modules support feeding them multiple files like for example unrar file1 file2 etc. (not sure if it was unrar that supported this, it's just an example), and then it only asks you once. But other modules do not. And once again, you're relying on their built in stuff. I'm looking for absolute uniformity. If I select a zip files, a rar file and a tar file and extract, I want the exact same message to be shown, shown only once etc.

Also, with extracting, the ability to select between "Extract Here" and "Extract each to separate folder", and for it to be absolutely certain is ridiculously important, to me at least.

This is basically where my issues came from.

Last edited by random0 (2022-05-03 04:44:47)

Offline

#4 2022-05-03 04:53:57

jasonwryan
Anarchist
From: .nz
Registered: 2009-05-09
Posts: 30,426
Website

Re: Why do archives have to be such a pain in Linux?

Sure, scratch your own itch. I was only pointing out that for some of us, it is not "such a pain".

┌─[Shiv ~]
└─╼ awk '$0 !/;extract */ {sum+=$0} END {print sum}' .zsh/histfile                                                                             
111

In the 667 days, 8 hours, 34 minutes, and 45 seconds of my recoeded Zsh history.


Arch + dwm   •   Mercurial repos  •   Surfraw

Registered Linux User #482438

Offline

#5 2022-05-03 05:09:18

random0
Member
Registered: 2022-04-07
Posts: 10

Re: Why do archives have to be such a pain in Linux?

Ok thanks
By the way I know some people may say "just use peazip", but that one was giving me errors with rar files. They got extracted supposedly successfully, but an error is an error. Unrar on the other hand gives me no errors whatsoever, hence why I'm willing to write a full on script.

I'm assuming I will finish this in the next few days (whenever I get more time).

Offline

#6 2022-05-03 16:48:19

Ferdinand
Member
From: Norway
Registered: 2020-01-02
Posts: 338

Re: Why do archives have to be such a pain in Linux?

Hm. If you want to create something for yourself, then by all means - but if you're happy with unrar then you should find engrampa working fine with Thunar, as it takes unrar as an optional dependency for extracting rar files. I've never had any problems, and it does extract all archives to separate folders smile

Offline

#7 2022-05-03 20:04:18

icar
Member
Registered: 2020-07-31
Posts: 562

Re: Why do archives have to be such a pain in Linux?

I have ever encountered only one issue with Linux regarding split zip files, which was solved by "unsplitting" them:

cat movie.zip* > movie.zip

Other compression formats have always worked perfectly fine.

Last edited by icar (2022-05-03 20:04:50)

Offline

#8 2022-05-03 20:11:21

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 30,483
Website

Re: Why do archives have to be such a pain in Linux?

Perhaps there are complexities that I've not run into, but `bsdtar` has always "just worked" for me for any archive format I've ran into.  I just confirmed it works fine on rar archives.  Note that bsdtar and tar share command line options but bsdtar handles a much wider range of archive formats and has worked in many situations where tar fails or produces frustrating results.


"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman

Online

#9 2022-05-04 04:51:58

random0
Member
Registered: 2022-04-07
Posts: 10

Re: Why do archives have to be such a pain in Linux?

Trilby wrote:

Perhaps there are complexities that I've not run into, but `bsdtar` has always "just worked" for me for any archive format I've ran into.  I just confirmed it works fine on rar archives.  Note that bsdtar and tar share command line options but bsdtar handles a much wider range of archive formats and has worked in many situations where tar fails or produces frustrating results.

That one seems limited. I actually ran into a little trouble with my extraction script. It's nothing I can't fix, but it just means it's gonna need a bunch more code. I thought unar can handle everything, but it can't handle password protected rar files. So I'm forced to use unrar, which is not as good in comparison and works in a totally different way. So unar is used for everything else, while unrar is used for rar files in particular.

I know the names are tricky lol. unar without an "r" and unRar lmao

Ferdinand wrote:

Hm. If you want to create something for yourself, then by all means - but if you're happy with unrar then you should find engrampa working fine with Thunar, as it takes unrar as an optional dependency for extracting rar files. I've never had any problems, and it does extract all archives to separate folders smile

That one seems just like FileRoller but maybe a bit more functional in the sense that it can handle multi-part rar files. I don't see how it could handle bulk extractions though, and specifically the way I want it to, where I can extract each archive to its own folder, or extract it directly (what's in it). Additionally, how would it handle duplicates and many archives with the same password, will it ask you every time? That's the whole reason I'm writing custom scripts is it to make bulk extractions super easy, guaranteed output structure and with non-existant user input once it gets going (other than password). Exctracting one archive at a time, or multiple ones, but with variable outputs is not acceptable to me.

Last edited by random0 (2022-05-04 04:53:06)

Offline

#10 2022-05-04 08:12:08

Ferdinand
Member
From: Norway
Registered: 2020-01-02
Posts: 338

Re: Why do archives have to be such a pain in Linux?

I'm afraid I must apologize for answering without testing properly, @random0; engrampa is rubbish at compressing; it doesn't even obey its own options for password and splitting tongue

I got a bit curious and tested out the extractions a bit:
I could not provoke any overwriting, but naming standards seems a little messy:

Making a folder with three zip files...

  1. "test.zip" (a bunch of files and folders, password protected, split)

  2. "test" (just normal files and folders)

  3. "test.somethingelse" (only one file)

...and then selecting all three in Thunar, and choosing to "Extract Here", produces three corresponding subdirectories:

  1. "test (2)" (one of the archive files is named "test" so that name is taken, otherwise the directory would have been named "test")

  2. "test_FILES" (it seems to use this naming scheme for all archives without filename extensions)

  3. none (extracts to the same folder as the archive file - this seems to happen only for the special case that the archive contains only one file and has an extension, otherwise it's case 2)

These things have nothing to do with engrampa, by the way - it's how unzip works - and so, presumably, will not be consistent across un-archivers.

So, you seem to have a valid point indeed; it is a bit of a mess, and it certainly would make sense to extract using a script, so you can control output naming, if that is important smile

As for passwords, though - to use one password for many archive files would require asking for a password once, and then try that password for all the files - keeping track of any failed files, and asking separately for those? That's a fairly specific functionality. Does Winrar do that?

I hope you'll share your script if/when it gets done smile

Offline

#11 2022-05-04 14:32:58

random0
Member
Registered: 2022-04-07
Posts: 10

Re: Why do archives have to be such a pain in Linux?

Ferdinand wrote:

I'm afraid I must apologize for answering without testing properly, @random0; engrampa is rubbish at compressing; it doesn't even obey its own options for password and splitting tongue

I got a bit curious and tested out the extractions a bit:
I could not provoke any overwriting, but naming standards seems a little messy:

Making a folder with three zip files...

  1. "test.zip" (a bunch of files and folders, password protected, split)

  2. "test" (just normal files and folders)

  3. "test.somethingelse" (only one file)

...and then selecting all three in Thunar, and choosing to "Extract Here", produces three corresponding subdirectories:

  1. "test (2)" (one of the archive files is named "test" so that name is taken, otherwise the directory would have been named "test")

  2. "test_FILES" (it seems to use this naming scheme for all archives without filename extensions)

  3. none (extracts to the same folder as the archive file - this seems to happen only for the special case that the archive contains only one file and has an extension, otherwise it's case 2)

These things have nothing to do with engrampa, by the way - it's how unzip works - and so, presumably, will not be consistent across un-archivers.

So, you seem to have a valid point indeed; it is a bit of a mess, and it certainly would make sense to extract using a script, so you can control output naming, if that is important smile

As for passwords, though - to use one password for many archive files would require asking for a password once, and then try that password for all the files - keeping track of any failed files, and asking separately for those? That's a fairly specific functionality. Does Winrar do that?

I hope you'll share your script if/when it gets done smile

Ok thanks. You could test my things if you want to. I just updated the post and added the extraction script.

Offline

Board footer

Powered by FluxBB