How to use zip to generate a new archive but not just refresh files in the archive and add files into it, on linux? - linux

Here, (on linux)
there is an existing archive named A.zip, which include File1 and File2:
A.zip:
File1
File2
and I run this command: zip A.zip File1 File3, then the archive A.zip becomes like:
A.zip:
File1
File2
File3
however, what I really want to get is a brand new archive A.zip! like:
A.zip:
File1
File3
I know it can be done by run rm A.zip and then run zip A.zip File1 File3, but it is not elegant and if I write these commands into a shell script so A.zip may not exist while the action to remove a non-existent file is not elegant as well.
Is there any options for me to get this done?

Use these option to works:
zip -FSr A.zip File1 File3
OPTIONS
-FS
Synchronize the contents of an archive with the files on the OS. Normally when an archive is updated, new files are added and changed files are updated but files that no longer exist on the
OS are not deleted from the archive. This option enables a new mode that checks entries in the archive against the file system. If the file time and file size of the entry matches that of
the OS file, the entry is copied from the old archive instead of being read from the file system and compressed. If the OS file has changed, the entry is read and compressed as usual. If
the entry in the archive does not match a file on the OS, the entry is deleted. Enabling this option should create archives that are the same as new archives, but since existing entries are
copied instead of compressed, updating an existing archive with -FS can be much faster than creating a new archive. Also consider using -u for updating an archive.
For this option to work, the archive should be updated from the same directory it was created in so the relative paths match. If few files are being copied from the old archive, it may be
faster to create a new archive instead.
Note that the timezone environment variable TZ should be set according to the local timezone in order for this option to work correctly. A change in timezone since the original archive was
created could result in no times matching and recompression of all files.
This option deletes files from the archive. If you need to preserve the original archive, make a copy of the archive first or use the --out option to output the updated archive to a new
file. Even though it may be slower, creating a new archive with a new archive name is safer, avoids mismatches between archive and OS paths, and is preferred.
-r
Travel the directory structure recursively; for example:
zip -r foo.zip foo
or more concisely
zip -r foo foo
In this case, all the files and directories in foo are saved in a zip archive named foo.zip, including files with names starting with ".", since the recursion does not use the shell's file-
name substitution mechanism. If you wish to include only a specific subset of the files in directory foo and its subdirectories, use the -i option to specify the pattern of files to be in‐
cluded. You should not use -r with the name ".*", since that matches ".." which will attempt to zip up the parent directory (probably not what was intended).
Multiple source directories are allowed as in
zip -r foo foo1 foo2
which first zips up foo1 and then foo2, going down each directory.
Note that while wildcards to -r are typically resolved while recursing down directories in the file system, any -R, -x, and -i wildcards are applied to internal archive pathnames once the di‐
rectories are scanned. To have wildcards apply to files in subdirectories when recursing on Unix and similar systems where the shell does wildcard substitution, either escape all wildcards
or put all arguments with wildcards in quotes. This lets zip see the wildcards and match files in subdirectories using them as it recurses.

Related

GZip an entire directory

i used the following:
gzip -9 -c -r <some_directory> > directory.gz
how do i decompress this directory ?
I have tried
gunzip directory.gz
i am just left with a single file and not a directory structure.
As others have already mentioned, gzip is a file compression tool and not an archival tool. It cannot work with directories. When you run it with -r, it will find all files in a directory hierarchy and compress them, i.e. replacing path/to/file with path/to/file.gz. When you pass -c the gzip output is written to stdout instead of creating files. You have effectively created one big file which contains several gzip-compressed files.
Now, you could look for the gzip file header/magic number, which is 1f8b and then reconstruct your files manually.
The sensible thing to do now is to create backups (if you haven't already). Backups always help (especially with problems such as yours). Create a backup of your directory.gz file now. Then read on.
Fortunately, there's an easier way than manually reconstructing all files: using binwalk, a forensics utility which can be used to extract files from within other files. I tried it with a test file, which was created the same way as yours. Running binwalk -e file.gz will create a folder with all extracted files. It even manages to reconstruct the original file names. The hierarchy of the directories is probably lost. But at least you have your file contents and their names back. Good luck!
Remember: backups are essential.
(For completeness' sake: What you probably intended to run: tar czf directory.tar.gz directory and then tar xf directory.tar.gz)
gzip will compress 1+ files, though not meant to function like an archive utility. The posted cmd-line would yield N compressed file images concatenated to stdout, redirected to the named output file; unfortunately stuff like filenames and any dirs would not be recorded. A pair like this should work:
(create)
tar -czvf dir.tar.gz <some-dir>
(extract)
tar -xzvf dir.tar.gz

How can we specify the unzip or 7za command in linux to extract multiple zip files into one folder while keeping all duplicates?

I currently have about 10 zip files I would like to extract into one folder. Each zip file contains around 1000 images. As a result, lots of the names of the images are duplicated. For example, in the first zip file, we have things like Img.jpg, Img(1).jpg, Img(2).jpg. I know that to extract multiple zip files into a single folder, I would do something like:
unzip '*.zip'
However, when it tries to put a file from the first zip file that has the same name as a file in the second zip file, it starts to ask:
replace duplicatefile.mp4? [y]es, [n]o, [A]ll, [N]one, [r]ename:
At this point, what do I do if I want to keep ALL files, including the duplicates, and possibly have them named to image(1).jpg instead?
In short, is there a way to call the unzip command on all the zip files, have them extracted into a single folder, without losing any files due to same names?
Thanks.
Invoke unzip --help for details.
But it appears unzip *.zip -n should do the trick?
(Make sure it does what you expect before going ahead!)

How do I copy differing content files from one directory to another?

There exists two directories: a/ and b/.
I'd like to copy all the files(recursively) from a/ into b/.
However, I only want to copy over an a file if its content is different than the already existing b file. If the corresponding b file does not exist, then you would still copy over the a file.
*by "corresponding file", I mean a files with the same name and relative path from their parent directories.
note:
The reason I don't want to overwrite a b file with the same exact contents, is because the b directory is being monitored by another program, and I don't want the file date to change causing the program to do more work than required.
I'm essentially looking for a way to perform a cp -rf a/ b/ while performing a diff check on each file. If the file's are different, perform the copy; otherwise skip the copy.
I see that cp has an update flag:
-u, --update
copy only when the SOURCE file is newer than the destination file or when the
destination file is missing
but this will not work because I'm not concerned about newer files; I'm concerned about different file contents.
Any shell language will do.
I've been attempting to get this to work by injecting my diff check into a find command:
find a/ ??? -exec cp {} b \;
This doesn't seem like an uncommon thing to do between two directories, so I'm hoping there is an elegant command line solution as aposed to me having to write a python script.
You can achieve this using rsync. Files or directories will be updated only if there is any new update in source folder.
$rsync -av --progress sourcefolder destinationfolder

zip a list of files at command-line linux

If I have a list of files I want to zip, how can I pass the list to zip?
cookbook/application/views/index.php
cookbook/application/controller/index.php
cookbook/js/index.js
....
cookbook/css/index.css
To do the above list one by one at the command-line would be like zip -r my.zip cookbook/css/index.css, where my.zip is in the same root directory as cookbook
Try
zip -r# my.zip < listfile
The -# flag tells zip to read file names from stdin.
If all files are in the same folder, you don't need to type each file that you want to include in the archive. Just invoke the command and specify their common folder like this:
zip -r cookbook.zip cookbook
All files inside the cookbook directory will be included in the zip archive.

using cp command to copy one set of files to another set (with same names) without overwrite and with renaming

Say I have a bunch of files in folder A:
1.txt
2.txt
3.txt
...
And a bunch of files in folder B, with the same names.
I want to move all the files from folder B into folder A, without losing any files. This means that some files need to be renamed. E.g., to 1cp.txt, 2cp.txt, 3cp.txt, ...
As I understand it, using
cp folderB/*.txt folderA/
will overwrite all files in folder A. Whereas, if I use the -n flag, this means that nothing will be copied, because -n prevents overwriting.
Does anyone know how I can achieve this copy and rename procedure, so that all files from both folders are retained?
You can use -b (backup each existing file). --backup accepts arguments to control behavior.
Otherwise you can create a bit more lines and check for your files in a more elaborated script.
First, you can rename it.
$ rename -n 's/\d{5}(\d{3})\.JPG$/BeachPics_$1\.jpg/' *.JPG
00000123.JPG renamed as BeachPics_123.jpg
00000124.JPG renamed as BeachPics_124.jpg
00000125.JPG renamed as BeachPics_125.jpg
and then copy it.
cp folderB/*.txt folderA/

Resources