2

I want to zip all files recursively but adding some prefix folder in front.

I tried:

zip -rq test.zip node_modules --prefix nodejs/

But getting error: zip error: Invalid command arguments (long option 'prefix' not supported)

Also tried with --transform, which seems to be not working in linux too.

My goal that all files with sub folders in node_modules/* should be with nodejs/node_modules/* path inside of a zip file

For the moment I'm using a hard way to do it:

mkdir nodejs
mv node_modules nodejs/
zip -rq ./$OUTPUT_DIR/dep-$DEP_VERSION.zip nodejs
mv nodejs/node_modules ./
rm -r nodejs

But I'm looking for more elegant solution. Any suggestion?

1

1 Answer 1

2

AFAIK zip doesn't have an option for that, but tar does have:

--transform, --xform EXPRESSION
  use sed replace EXPRESSION to transform file names.

So:

$ mkdir node_modules
$ touch node_modules/file{1..3}
$ tree node_modules/
node_modules/
├── file1
├── file2
└── file3

0 directories, 3 files
$
$ tar czf test.tgz --transform 's|^|nodejs/|' node_modules/
$ tar -tf test.tgz 
nodejs/node_modules/
nodejs/node_modules/file2
nodejs/node_modules/file3
nodejs/node_modules/file1
$
$ tar xf test.tgz
$ tree nodejs/
nodejs/
└── node_modules
    ├── file1
    ├── file2
    └── file3

1 directory, 3 files

If however your end result must be a zip archive then you can use tar without compression to save time and resources then extract the archive and compress it with zip afterwards ... Or you can use a function that will automatically do this for you like this:

my_zip () {
p="$1" # First argument "archive prefix directory name"
d="$2" # Second argument "source directory name"
z="$3" # Third argument "result ZIP archive name without .zip"
[ -e "$p" -o -e "${z}.zip" ] && return "Prefix directory name: $p Or target zip file name: ${z}.zip exist in PWD, cannot continue"
tmp="$(mktemp)"
tar cf "$tmp" --transform "s|^|$p/|" "$d"
tar xf "$tmp"
zip -rq "${z}.zip" "$p"
rm "$tmp"
rm -r "$p"
}

Then use the function by its name my_zip passing properly quoted arguments "prefix", "source_directory" and "zip_archive_name" in that order like so:

$ my_zip "nodejs2" "node_modules" "test2"
$ unzip -l test2.zip 
Archive:  test2.zip
  Length      Date    Time    Name
---------  ---------- -----   ----
        0  2023-04-24 17:11   nodejs2/
        0  2023-04-24 16:58   nodejs2/node_modules/
        0  2023-04-23 19:51   nodejs2/node_modules/file2
        0  2023-04-23 19:51   nodejs2/node_modules/file3
        0  2023-04-23 19:51   nodejs2/node_modules/file1
---------                     -------
        0                     5 files
$
$ unzip -q test2.zip
$ tree nodejs2/
nodejs2/
└── node_modules
    ├── file1
    ├── file2
    └── file3

1 directory, 3 files
3
  • Any way to convert it to zip file? I'm not sure if tgz will be supported for what I need.
    – Kostanos
    Apr 24 at 12:02
  • @Kostanos I updated the answer with a function that I wrote to do that ... Unfortunately no utility/package in the repositories can do that AFAIK.
    – Raffa
    Apr 24 at 14:17
  • Oh man, it is unzipping and zipping again, doesn't make sens. In this case, it is easier copy folder to necessary path, zip it and delete after. Or even faster move it, zip it, and move it back. Any way, thank you for trying
    – Kostanos
    Apr 24 at 17:29

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .