Another 7-zip script

Discuss and share scripts and script files...
Plastic
Posts: 36
Joined: 08 Sep 2008 00:18

Another 7-zip script

Post by Plastic »

Hello everyone,

I made a simple script with 7-zip which zip the selected files.
The behavior is as follows :
- 1 file FILE selected -> FILE.zip
- several files selected (FOLDER/file1, FOLDER/file2, ...) -> FOLDER.zip

In clear, if one file is selected, the zip take the name of the file, if more, the zip take the name of the folder.

====================

NEW VERSION (2010/08/16):
- Centralization of the executable path in _get_exec
- Extraction of single/multiple archive in current folder or in a subfolder (using the archive name)
- Several compression type (currently zip and 7z, easy to add more)
- Ability to compress in 1 archive per item (file or folder)
- Rewritten to use new conditional and loop syntax (at last !)
- Added some suggestions made by lukescammell
- Added options by archive type
- Corrected a bug which could add some unwanted items to the archives (apparently caused by -r option)
- For whose who compress really long filepath, the script use 7-zip file list option when all the filepath are longer than 1000 characters. Default file name and deletion of the filelist are configurable.
Please be aware that by setting $g_delete_list_file to 1, the script become modal (you can't do other things with XY while it runs) as I have to wait for completion before the deletion.
- Corrected ". in folder name" bug
- Adapted for change in beta v9.40.0007 (DO NOT UPDATE IF YOU USE A PREVIOUS VERSION)
- Added a header

These last changes are thanks to lukescammell. Thank you guy!

Code: Select all

/* Title:       Another 7-Zip Script
* Author:       Plastic - http://www.xyplorer.com/xyfc/memberlist.php?mode=viewprofile&u=778
* URL:          http://www.xyplorer.com/xyfc/viewtopic.php?f=7&t=3487
* Last update : 2010-08-18
*/

/** CONFIG **/
// 7zip executable
"_get_config"
    global $g_exec, $g_filelist_path, $g_delete_filelist;
   
    //$g_exec = "C:\Program Files\7-Zip\7z.exe";
    $g_exec = "<xypath>\..\7-ZipPortable\App\7-Zip\7z.exe";
   
    $g_filelist_path = "<xyscripts>\7zip.filelist";
   
    // Set to 1 to force deletion of the filelist after completion.
    // WARNING: This render the script modal
    $g_delete_filelist = 0;

// 7zip option by format (Notice: -r option is unnecessary)
"_get_7z_add_options"
    global $g_options;
    $g_options = "-mx=9 -ms=on -mmt=4 -ssw";
   
"_get_7z_extract_options"
    global $g_options;
    $g_options = "";

"_get_zip_add_options"
    global $g_options;
    $g_options = "";
   
"_get_zip_extract_options"
    global $g_options;
    $g_options = "";

/** MENU **/
"Zip item(s) : zip"
    sub "_init";
   
    global $g_archive_type;
    $g_archive_type = "zip";
   
    sub "_do_compress_1archive"

"Zip items (1 archive/item) : mzip"
    sub "_init";
   
    global $g_archive_type;
    $g_archive_type = "zip";
   
    sub "_do_compress_Narchives"
   
"7z item(s) : 7z"
    sub "_init";
   
    global $g_archive_type;
    $g_archive_type = "7z";
   
    sub "_do_compress_1archive"

"7z items (1 archive/item) : m7z"
    sub "_init";
   
    global $g_archive_type;
    $g_archive_type = "7z";
   
    sub "_do_compress_Narchives"
-

"Extract here : extract"
    sub "_init";
   
    global $g_list_items, $g_list_length, $g_env_curpath;
    global $param_extract_path, $param_item;
    global $param_item_path, $out_item_name;
   
    $i = 1;
    while ($i <= $g_list_length) {
        $item_path = gettoken($g_list_items, $i, "|");
     
        $param_extract_path = "$g_env_curpath";
        $param_item = $item_path;
        sub "_do_extract";
     
        $i = $i + 1;
    }

"Extract in <subfolder> : extract_subfolder"
    sub "_init";
   
    global $g_list_items, $g_list_length, $g_env_curpath;
    global $param_extract_path, $param_item;
    global $param_item_path, $out_item_name;
   
    $i = 1;
    while ($i <= $g_list_length) {
        $item_path = gettoken($g_list_items, $i, "|");
     
        $param_item_path = $item_path;
        sub "_get_item_basename";
        // Return $out_item_name
     
        $param_extract_path = "$g_env_curpath\$out_item_name";
        $param_item = $item_path;
        sub "_do_extract";
     
        $i = $i + 1;
    }

-
"Edit script : edit"
   self $scriptFile, file;
   Open $scriptFile;
-
"Cancel"

/** PRIVATE **/
"_init"
    sub "_get_config";
    sub "_get_list";
    sub "_get_env";
    sub "_check";
   
"_get_list"
    // Get selected list items
    global $g_list_items, $g_list_length;
    $g_list_items = getinfo("SelectedItemsPathNames", "|") . "|";
    $g_list_length = getinfo("CountSelected");
   
    $i = 1;
    while ($i <= $g_list_length) {
        $item_path = gettoken($g_list_items, $i, "|");
        if (exists($item_path) == 2) { // Folder -> Add "\" to work on folder content
            replace $g_list_items, $g_list_items, "$item_path|", "$item_path\|";
        }
        $i = $i + 1;
    }
   
    substr $g_list_items, $g_list_items, 0, -1; // Delete last separator
   
"_get_env"
    // Get useful environment variables
    global $g_env_curpath, $g_env_curfolder, $g_env_curbase;
    $g_env_curpath = <curpath>;
    $g_env_curfolder = <curfolder>;
   
"_check"
    // Check if parameters are ok
    global $g_list_length;
    end $g_list_length <= 0;

"_get_item_basename"
    // Get a full path in $param_item_path, and returne base in $out_item_name
    // ex: c:\dir1\dir2\base.ext => base
    //      c:\dir1\dir2\ => dir2
    global $param_item_path;
    global $out_item_name;
   
    $out_item_name = $param_item_path;
   
    // Detect folder path. Folder path ends with "\" so we have to find if the path ends with a "\"
    // No reverse find for now, so we add a special character to do the trick
    $out_item_name = $out_item_name . "{";
    strpos $is_folder, $out_item_name, "\{";
    if ($is_folder >= 0) {
        $is_folder = 1;
        // Remove special char with last "\"
        replace $out_item_name, $out_item_name, "\{";
    }
    else {
        $is_folder = 0;
        // Remove special char
        replace $out_item_name, $out_item_name, "{";
    }
   
    strpos $last_slash_index, $out_item_name, "\";
    $last = $last_slash_index;
    while ($last_slash_index >= 0 && $last_slash_index < strlen($out_item_name)) {
        strpos $last_slash_index, $out_item_name, "\", $last_slash_index + 1;
        if ($last_slash_index != -1) {
            $last = $last_slash_index;
        }
    }
    $last_slash_index = $last;
   
    if ($last_slash_index != -1) {
        substr $out_item_name, $out_item_name, $last_slash_index + 1;
    }
   
    if ($is_folder == 0) {
        // Folder -> Do nothings
        // File -> Remove extension
        strpos $last_dot_index, $out_item_name, ".";
        $last = $last_dot_index;
        while ($last_dot_index >= 0 && $last_dot_index < strlen($out_item_name)) {
            strpos $last_dot_index, $out_item_name, ".", $last_dot_index + 1;
            if ($last_dot_index != -1) {
                $last = $last_dot_index;
            }
        }
        $last_dot_index = $last;
       
        if ($last_dot_index > 0) {
            strlen $length, $out_item_name;
            $last_dot_right = $last_dot_index - $length;
            substr $out_item_name, $out_item_name, 0, $last_dot_right;
        }
    }
   
"_do_compress_1archive"
    // 1 archive for all items
    global $g_list_items, $g_list_length, $g_env_curpath, $g_env_curfolder;
    global $g_filelist_path;
    global $param_items, $param_archive_path, $param_archive_name, $param_use_filelist;
   
    $param_archive_path = $g_env_curpath;
   
    if ($g_list_length == 1) {
        // 1 item -> archive name = item name
        global $param_item_path, $out_item_name;
        $param_item_path = $g_list_items;
        sub "_get_item_basename";
        $param_archive_name = $out_item_name;
    }
    else {
        // N items -> archive name = folder name
        $param_archive_name = $g_env_curfolder;
    }
   
    // Use file list g_list_items is too big
    if (strlen($g_list_items) > 1000) {
        replace $listfile_data, $g_list_items, "|", chr(10);
        if (writefile($g_filelist_path, $listfile_data) != 0) {
            $param_use_filelist = 1;
            sub "_do_compress";
        }
    } else {
        $g_filelist_path = "";
        replace $param_items, $g_list_items, "|", '" "';
        sub "_do_compress";
    }

"_do_compress_Narchives"
    // N archives : 1 archive per item
    global $g_list_items, $g_list_length, $g_env_curpath;
    global $param_items, $param_archive_path, $param_archive_name;
    global $param_item_path, $out_item_name;
   
    $param_archive_path = $g_env_curpath;   
   
    $i = 1;
    while ($i <= $g_list_length) {
        $item_path = gettoken($g_list_items, $i, "|");
     
        $param_item_path = $item_path;
        sub "_get_item_basename";
        // Return $out_item_name
     
        $param_archive_name = $out_item_name;
        $param_items = $item_path;
        sub "_do_compress";
     
        $i = $i + 1;
    }

// ** Simple actions **
"_do_compress"
    global $g_exec, $g_archive_type, $g_options;
    global $param_items, $param_archive_path, $param_archive_name, $param_use_filelist;
    global $g_filelist_path, $g_delete_filelist;
    sub "_get_" . $g_archive_type . "_add_options";
   
    if ($param_use_filelist == 1 and $g_filelist_path != "") {
        if ($g_delete_filelist == 1) {
            // Using file list parameter, we should wait for the command to end in order to delete the file
            run """$g_exec"" a -t$g_archive_type ""$param_archive_path\$param_archive_name.$g_archive_type"" $g_options @""$g_filelist_path""", , 1;
            delete 1,0,$g_filelist_path;
        }
        else {
            run """$g_exec"" a -t$g_archive_type ""$param_archive_path\$param_archive_name.$g_archive_type"" $g_options @""$g_filelist_path""", , 0;
        }
    }
    else {
        run """$g_exec"" a -t$g_archive_type ""$param_archive_path\$param_archive_name.$g_archive_type"" $g_options ""$param_items""", , 0;
    }

"_do_extract"
    global $g_exec, $g_options;
    global $param_extract_path, $param_item;
    // TODO Detect archive type
    $g_archive_type = "7z";
    sub "_get_" . $g_archive_type . "_extract_options";
    run """$g_exec"" x -o""$param_extract_path"" $g_options ""$param_item""", , 0;

Have fun!
Last edited by Plastic on 18 Aug 2010 21:09, edited 13 times in total.

Plastic
Posts: 36
Joined: 08 Sep 2008 00:18

Re: Another 7-zip script

Post by Plastic »

[Useless post]
Last edited by Plastic on 07 Sep 2009 23:14, edited 2 times in total.

stanmarsh
Posts: 85
Joined: 10 Mar 2009 07:43

Re: Another 7-zip script

Post by stanmarsh »

hi plastic,

can i request for an option to archive several files/folders individually with their filename as the name of the created 7z? this is an option lacking in 7zip, winrar has this option "put each file on each archive" it also works with folders too. i found several links that pertains to this.
http://sourceforge.net/forum/forum.php? ... m_id=45797
http://sourceforge.net/forum/forum.php? ... m_id=45797
http://aarmstrong.org/tutorials/mass-zi ... batch-file

thanks

Plastic
Posts: 36
Joined: 08 Sep 2008 00:18

Re: Another 7-zip script

Post by Plastic »

Hi stanmarsh,

I updated my script to add the option you requested.

I used this occasion to refactor my code, as I was finding it more and more confusing ;)

stanmarsh
Posts: 85
Joined: 10 Mar 2009 07:43

Re: Another 7-zip script

Post by stanmarsh »

Hi Plastic,

sorry for the late reply,thanks for this great script! really useful script! :D

lukescammell
Posts: 744
Joined: 28 Jul 2006 13:15
Location: Kent, UK
Contact:

Re: Another 7-zip script

Post by lukescammell »

Hmm, this script is crashing my 7.90.410 when I try and load it... any ideas?
Used to update to the latest beta every day. Now I have children instead…
Windows 10 Pro x64 (everywhere except phone…)

Plastic
Posts: 36
Joined: 08 Sep 2008 00:18

Re: Another 7-zip script

Post by Plastic »

Hello,

I just tried it with the latest beta (7.90.0412) and everythings seems to work fine.
Did you update the path to 7-zip in the script ? It's in the _get_exec subroutine.

What kind of error do you get ? Have your an error message ?


Regards

lukescammell
Posts: 744
Joined: 28 Jul 2006 13:15
Location: Kent, UK
Contact:

Re: Another 7-zip script

Post by lukescammell »

It's still happening with 414 as well :/ There's no information, it just kills XY and the standard windows error report comes up to be sent. Probably just something it doesn't like about Windows 7 I guess, it's jsut odd that no other scripts seem to cause this (including the other 7zip script). Most irritating as your script has several features I'd find highly useful!
Used to update to the latest beta every day. Now I have children instead…
Windows 10 Pro x64 (everywhere except phone…)

TheQwerty
Posts: 4373
Joined: 03 Aug 2007 22:30

Re: Another 7-zip script

Post by TheQwerty »

lukescammell wrote:It's still happening with 414 as well :/ There's no information, it just kills XY and the standard windows error report comes up to be sent. Probably just something it doesn't like about Windows 7 I guess, it's jsut odd that no other scripts seem to cause this (including the other 7zip script). Most irritating as your script has several features I'd find highly useful!
You have set the INI tweak ScriptRecursionWarningOff to 1, correct?

(This script should probably be re-written to use while and it would avoid the need for disabling the recursion warning. Or you could just add 'Setting("AllowRecursion", 1);')

Plastic
Posts: 36
Joined: 08 Sep 2008 00:18

Re: Another 7-zip script

Post by Plastic »

Alright, I'll test it under Win7 when I get the occasion (maybe this week-end).

I agree it should be rewritten using the new while keyword, but sometimes it's better to stick to the old trusted way instead of jumping to hot new feature. I guess while is no longer "hot new" ;)

lukescammell
Posts: 744
Joined: 28 Jul 2006 13:15
Location: Kent, UK
Contact:

Re: Another 7-zip script

Post by lukescammell »

Code: Select all

; Tweak: set to 1 to turn off the recursion checker
ScriptRecursionWarningOff=1
Check. Thanks for taking a look ;)
Used to update to the latest beta every day. Now I have children instead…
Windows 10 Pro x64 (everywhere except phone…)

Plastic
Posts: 36
Joined: 08 Sep 2008 00:18

Re: Another 7-zip script

Post by Plastic »

New version -> Rewritten to use new conditional and loop syntax (at last !)

lukescammell
Posts: 744
Joined: 28 Jul 2006 13:15
Location: Kent, UK
Contact:

Re: Another 7-zip script

Post by lukescammell »

Loads better, thanks :D It's really nice having the individual archiving and extracting! :mrgreen:

And now some (hopefully) constructive criticism! I realise it's long, but it's really just me nit picking for the most part and a couple of minor bugs :)
  1. Please can you put the 7z.exe path config line at the top? It just makes life easier to change it if it's the first thing you see - most people don't have 7-Zip installed on their E drive :P
  2. Recommend you change the default path to C:\Program Files\7-Zip\7z.exe
  3. Relative paths to 7z.exe no longer seem to work - they did with your old script - any chance of fixing that?
  4. I would like to set some different options for 7z to zip (cos the 7z options don't work with zip), specifically -r -mx=9 -ms=on -mmt=4 instead of just -r because it uses more threads and creates smaller files. I tried putting this into line 189, but it causes the zip option to fail with an error. Could you create a way for this to be possible please?
  5. Selecting 2 (or more) files of the same name, but differing file extensions and then "1 archive/item"ing the selection has odd results. Sometimes a single compressed file will be created with all of the items in and other items you get orphaned .tmp files and only some of the files are in the resultant compressed file. Possible solution to this - can the script create files with their file extension in the name of the compressed file? ie. XYplorer Automatic Updater.ini would be compressed to XYplorer Automatic Updater.ini.7z
  6. I suggest the following:
    Line 1 (press "p" to zip)

    Code: Select all

    "Zi&p item(s) : zip"
    Line 17 (press "z" to 7zip)

    Code: Select all

    "7&z item(s) : 7z"
    Line 34 (press "h" to extract here)

    Code: Select all

    "Extract &here : extract"
    Line 52 (press "x" to extract to folder)

    Code: Select all

    "E&xtract in <subfolder> : extract_subfolder"
All of these changes make sense because I have set up a User-Defined Command of Ctrl+Shift+Z. Since I prefer the superior abilities of the 7z format and extracting to folders (because I don't trust people to compress with a folder), that means I just hit Ctrl+Shift+Z and then either Z to compress or X to extract - nice and fast :)

To setup a UDC of Ctrl+Shift+Z for this excellent script...
...do the following (look at the image below and it all makes sense :P):
  1. Press Ctrl+Alt+F9 on the keyboard to get the Manage User-Defined Commands dialogue box up
  2. Select a Category of Load Script File
  3. Click New and then Add New Command or press Insert on the keyboard
  4. The focus will now be on the Script File: text box, replace the highlighted word New with 7zip (or whatever you called your script file, I've named mine 7zip.xys, so I put in 7zip - WITHOUT the .xys)
  5. Next click on Assign Keyboard Shortcut, this brings up the Free Keyboard Shortcuts dialogue box
  6. Press Ctrl+Shift+Z on the keyboard
  7. Click OK to save your selection and close the dialogue
  8. Finally, click OK to save your new UDC and close the Manage User-Defined Commands dialogue box
Image
Hope this helps someone as it took me an age to figure out how to fire scripts using UDCs - maybe I'm just slow...
Used to update to the latest beta every day. Now I have children instead…
Windows 10 Pro x64 (everywhere except phone…)

lukescammell
Posts: 744
Joined: 28 Jul 2006 13:15
Location: Kent, UK
Contact:

Re: Another 7-zip script

Post by lukescammell »

Seems you've made some of the changes I suggested, thanks :)

Found a bug though I think... I just tried selecting all the files in a pretty deep directory

Code: Select all

C:\Users\luke\Downloads\My Dropbox\PortableApps\Firefox2.0Portable\App\Firefox\components\
I had that directory open, Ctrl+A'd to select all and then fired the script (using Ctrl+Shift+Z as mentioned above) and hit Z (for 7z to a single file) and I got this error:
Image

Basically, "it dun work!" Yet the old script works just fine...

P.S. would it be useful if there was a "copy script error details to clipboard" button on this dialogue for pasting to scripting authors?
Used to update to the latest beta every day. Now I have children instead…
Windows 10 Pro x64 (everywhere except phone…)

admin
Site Admin
Posts: 60561
Joined: 22 May 2004 16:48
Location: Win8.1 @100%, Win10 @100%
Contact:

Re: Another 7-zip script

Post by admin »

lukescammell wrote:Seems you've made some of the changes I suggested, thanks :)

Found a bug though I think... I just tried selecting all the files in a pretty deep directory

Code: Select all

C:\Users\luke\Downloads\My Dropbox\PortableApps\Firefox2.0Portable\App\Firefox\components\
I had that directory open, Ctrl+A'd to select all and then fired the script (using Ctrl+Shift+Z as mentioned above) and hit Z (for 7z to a single file) and I got this error:
Image

Basically, "it dun work!" Yet the old script works just fine...

P.S. would it be useful if there was a "copy script error details to clipboard" button on this dialogue for pasting to scripting authors?
"The data area passed to a system call is too small" -- wow, never heard of this error. This message comes from "the system". I would assume there's a limit around 2048 characters. Could it be that you reached that limit?

"copy script error details to clipboard" : yes, good idea.

Post Reply