Score:1

Add prefix folder name to each file inside of the zip

mq flag

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?

Score:2
jp flag

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
mq flag
Any way to convert it to zip file? I'm not sure if tgz will be supported for what I need.
Raffa avatar
jp flag
@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.
mq flag
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
I sit in a Tesla and translated this thread with Ai:

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.