ouch icon indicating copy to clipboard operation
ouch copied to clipboard

Almost deleted my home directory

Open salahoued opened this issue 8 months ago • 7 comments

It my seem weird using -d ./ because ouch extract in the current directory already, I'm not sure what I was trying to do back then.. :(

But when I did run ouch d -y -d ./ Downloads/Compressed/<file> almost deleted my HOME directory, and I'm not sure why some other directories and files weren't deleted. What I observed is .config/* .cargo .var Musique some file in $HOME were deleted and .local .cache Document Images a so-config where I stowed my dotfiles and some other files weren't.

salahoued avatar Apr 29 '25 22:04 salahoued

So sorry to hear that, when running with -d . it definitely shouldn't try replacing the current dir, I don't see why it would try that.

Thanks for reporting!

marcospb19 avatar May 01 '25 07:05 marcospb19

Just lost a bunch of files in a directory the same way, ouch! 😅 The things in life that teach you should back up (too late). I'm curious, does the replacing the directory effect of the --dir flag have any use case that warrants it being the default behavior?

N4taaa avatar Jul 24 '25 08:07 N4taaa

Yeah, I can confirm this.

This will decompress archive without problem to empty folder:

ouch decompress ~/random.zip -d ~/emptyfolder/
[INFO] extracted ( 45.46 kiB) "test.txt"
[INFO] Successfully decompressed archive in /home/test/emptyfolder/ (1 files)

But if you try this with folder that have some files/folders, they will be deleted and replaced by files from archive:

ouch decompress ~/random.zip -d ~/somefilesandfolders/
Do you want to overwrite somefilesandfolders? [y/n/r]
y
[INFO] extracted ( 45.46 kiB) "test.txt"
[INFO] Successfully decompressed archive in /home/test/somefilesandfolders/ (1 files)

roland-5 avatar Jul 28 '25 08:07 roland-5

Some changes are being made in the main branch, we're adding the much needed capacity to merge folders instead of overwriting them.

The code will ask on every conflict whether you want to overwrite or merge.

How can we improve that? Should it merge by default on folder conflicts, and only ask for overwriting on file conflicts?

Maybe we remove -y and yes being the "overwrite" option as people are inclined to just type 'y' without thinking much about it.

Instead of 'y/n' maybe we could ask m for merge, o for overwrite, s for skip and q for quit??

Should it also merge to the top-level folder where --dir is provided, and then, ask for each conflict?

Thoughts on this? I need more input to come up with something decent. Ideally I don't have to change this more than once.

marcospb19 avatar Jul 28 '25 16:07 marcospb19

Perhaps I and those before me in this topic misunderstand this function. I will present my use case:

I have archive from a friend and want extract it to folder vacations, and this is how this folder looks like before any operation

ls vacations
2020-07-20
2021-08-10
2022-07-14
2023-08-15
2024-06-13

In archive from a friend I have folder 2025-06-30 with pictures. Why If I do

ouch decompress ~/vacation-2025-06-30.zip -d ~/vacations/

and type y/yes it will destroy everything in vacations and replace it with only folder 2025-06-30 from archive? It should add this new folder to the others.

If I choose n/no, nothing will happen - the archive will not be unpacked. And if I choose r/rename, a new folder with the suffix _1 will be created in the parent folder - So there will be a vacations folder with old content and this new vacations_1 folder with photos from a friend.

ouch decompress ~/vacation-2025-06-30.zip -d ~/vacations/
r
[INFO] extracted ( 45.46 kiB) "vacations_1/photo1.png"
[INFO] extracted ( 46.46 kiB) "vacations_1/photo2.png"
[INFO] extracted ( 43.46 kiB) "vacations_1/photo3.png"
[INFO] extracted ( 49.46 kiB) "vacations_1/photo4.png"
[INFO] Successfully decompressed archive in /home/test/vacations/ (4 files)

Why in last line it says [INFO] Successfully decompressed archive in /home/test/vacations/ (4 files) if it unpacked it to different folder (vacations_1)?

I would understand if in archive from my friend was folder named 2020-07-20, 2021-08-10, 2022-07-14, 2023-08-15 or 2024-06-13 since these folders already exist in the vacations folder, so there would be a file/folder name conflict.

If the archive contains files/folders that are not contained in the folder it is unpacked to, it should not ask for anything. If a folder exists, only then should it ask whether to merge, replace, rename or skip it. Similarly, if files exist with the same name, only then should it ask whether to replace, rename or skip them.

tree
 /home/test/vacations
├──  2020-07-20
│   ├──  photo20-01.png
│   ├──  photo20-02.png
│   ├──  photo20-03.png
│   └──  r-lake
│       └──  lake20-01.png
├──  2021-08-10
│   ├──  photo21-01.png
│   ├──  photo21-02.png
│   └──  photo21-03.png
├──  2022-07-14
│   ├──  photo22-01.png
│   ├──  photo22-02.png
│   ├──  photo22-03.png
│   └──  photo22-04.png
├──  2023-08-15
│   ├──  photo23-20.png
│   ├──  photo23-21.png
│   └──  photo23-22.png
└──  2024-06-13
    ├──  photo24-01.png
    ├──  photo24-02.png
    ├──  photo24-03.png
    └──  photo24-04.png

Let's say, folder from a friend looks like this:

 /home/test/vacation-2025-06-30.zip
├──  2024-06-13
│   ├──  photo24-01.png
│   ├──  photo24-02.png
│   ├──  photo24-11.png
│   └──  photo24-12.png
└──  2025-06-30
    ├──  photo25-01.png
    ├──  photo25-02.png
    ├──  photo25-03.png
    └──  photo25-04.png

The 2024-06-13 folder already exists in my vacations folder, so it should ask whether to merge, replace, rename or skip him. Then, the first two files have the same names in my 2024-06-13 folder and in its archive: photo24-01.png and photo24-02.png, and it should ask whether I want to replace them with copies from the archive rename or skip them. The other two photos in this folder have different names, so there shouldn't be any interaction. So it should looks like this:

ouch decompress ~/vacation-2025-06-30.zip -d ~/vacations/

Folder name conflict: 2024-06-13? [merge/replace/rename/skip]
merge
[INFO] Folder 1 merged with "/home/test/vacations/2024-06-13"

File name conflict: 2024-06-13/photo24-01.png? [replace/rename/skip]
replace
[INFO] extracted ( 48.56 kiB) "2024-06-13/photo24-01.png"

File name conflict: 2024-06-13/photo24-02.png? [replace/rename/skip]
skip

[INFO] extracted ( 45.42 kiB) "2024-06-13/photo24-11.png"
[INFO] extracted ( 41.23 kiB) "2024-06-13/photo24-12.png"
[INFO] Folder 1 extracted to "/home/test/vacations/2025-06-30/"
[INFO] extracted ( 47.41 kiB) "2025-06-30/photo25-01.png"
[INFO] extracted ( 40.01 kiB) "2025-06-30/photo25-02.png"
[INFO] extracted ( 48.28 kiB) "2025-06-30/photo25-03.png"
[INFO] extracted ( 45.46 kiB) "2025-06-30/photo25-04.png"
[INFO] Successfully decompressed archive in /home/test/vacations/ (9 files)

Final output, where 2024-06-13/photo24-01.png was the only replaced file:

 /home/test/vacations
├──  2020-07-20
│   ├──  photo20-01.png
│   ├──  photo20-02.png
│   ├──  photo20-03.png
│   └──  r-lake
│       └──  lake20-01.png
├──  2021-08-10
│   ├──  photo21-01.png
│   ├──  photo21-02.png
│   └──  photo21-03.png
├──  2022-07-14
│   ├──  photo22-01.png
│   ├──  photo22-02.png
│   ├──  photo22-03.png
│   └──  photo22-04.png
├──  2023-08-15
│   ├──  photo23-20.png
│   ├──  photo23-21.png
│   └──  photo23-22.png
├──  2024-06-13
│   ├──  photo24-01.png
│   ├──  photo24-02.png
│   ├──  photo24-03.png
│   ├──  photo24-04.png
│   ├──  photo24-11.png
│   └──  photo24-12.png
└──  2025-06-30
    ├──  photo25-01.png
    ├──  photo25-02.png
    ├──  photo25-03.png
    └──  photo25-04.png

roland-5 avatar Jul 29 '25 09:07 roland-5

Some changes are being made in the main branch, we're adding the much needed capacity to merge folders instead of overwriting them.

The code will ask on every conflict whether you want to overwrite or merge.

How can we improve that? Should it merge by default on folder conflicts, and only ask for overwriting on file conflicts?

When using -d /targetdir there should not be any need to delete targetdir and create a new one, even when overwriting. If it exists, the contents could be deleted/overwritten, but there is no use case where deleting a directory and recreating it will result in a different directory.

When an application asks me if I want it to overwrite files during decompression, I would assume that doing so will only overwrite those files that conflict with the directory. I may have unpacked an archive, added some new files, modified some of the unpacked files, decided to undo those modifications to the archive files by unpacking the archive again, fully expecting that none of the new files will be touched? Why would they, the application asked me if I intended to overwrite conflicting files, yet the current behavior of ouch will just delete everything.

The only solution I see to this is to iterate through the archive files and overwrite only conflicting files, while directives can always be left untouched

valoq avatar Jul 30 '25 10:07 valoq

I was bit by this bug and it removed ~/.local/share.

How can we improve that? Should it merge by default on folder conflicts, and only ask for overwriting on file conflicts?

Should it also merge to the top-level folder where --dir is provided, and then, ask for each conflict?

From someone who has been working with software for decades, here's what makes sense to me.

  1. Clearly indicate breaking changes. The releases page is used to indicate what changed. That's great! It doesn't clearly indicate breaking changes. Perhaps prefixing breaking changes with BREAKING: to indicate it's a breaking change.
  2. The README.md and CONTRIBUTING.md does not mention anything about following Semantic Versioning. It looks like Ouch is following SemVer, but with no mention of it, you might not be.
    • Note: I searched the repo and the CHANGELOG.md mentions Semantic Versioning, so you are using it.
  3. ouch decompress --help for the --dir option is the same for version 0.5.1 and 0.6.1 even though there was a breaking change. Since the --dir option acts differently between the two versions, the help should clearly indicate how ouch works.
    • Note: I did not test 0.6.0 but I'm assuming it works the same as 0.6.1.

Suggestions

Here's what I suggest. It's about clarity and advertising breaking changes. You have every right to make breaking changes. What rubs people the wrong way is the breaking change was not advertised and ouch removed files it should not have.

  1. Add the semantic versioning statement to the CONTRIBUTING.md file. This makes it clear for contributors that the code should follow semantic versioning.
  2. Clearly indicate breaking changes in the CHANGELOG.md. The word "break" or "breaking" was not found in that document.
  3. If there is a breaking change, add it to the README.md. Since you don't have a blog or website (GitHub pages) to advertise the changes, the README.md can highlight breaking changes.
    1. Relating to the above, create a "Releases" section and link to the CHANGELOG.md.
    2. (optional) Likewise, add a link to the CHANGELOG.md from the Releases page.
  4. Update the --help for the --dir option to indicate ouch will remove or replace the contents of <OUTPUT_DIR>. <-- This is the breaking change!

Versions and --help

Notice the help is the same for --dir for both versions.

ouch 0.5.1

ouch decompress --help

Decompresses one or more files, optionally into another folder

Usage: ouch decompress [OPTIONS] <FILES>...

Arguments:
  <FILES>...  Files to be decompressed

Options:
  -d, --dir <OUTPUT_DIR>  Place results in a directory other than the current one
  -y, --yes               Skip [Y/n] questions positively
  -n, --no                Skip [Y/n] questions negatively
  -A, --accessible        Activate accessibility mode, reducing visual noise [env: ACCESSIBLE=]
  -H, --hidden            Ignores hidden files
  -q, --quiet             Silences output
  -g, --gitignore         Ignores files matched by git's ignore files
  -f, --format <FORMAT>   Specify the format of the archive
  -h, --help              Print help

ouch 0.6.1

ouch decompress --help

Decompresses one or more files, optionally into another folder

Usage: ouch decompress [OPTIONS] <FILES>...

Arguments:
  <FILES>...  Files to be decompressed, or "-" for stdin

Options:
  -d, --dir <OUTPUT_DIR>     Place results in a directory other than the current one
  -y, --yes                  Skip [Y/n] questions, default to yes
  -n, --no                   Skip [Y/n] questions, default to no
  -r, --remove               Remove the source file after successful decompression
  -A, --accessible           Activate accessibility mode, reducing visual noise [env: ACCESSIBLE=]
  -H, --hidden               Ignore hidden files
  -q, --quiet                Silence output
  -g, --gitignore            Ignore files matched by git's ignore files
  -f, --format <FORMAT>      Specify the format of the archive
  -p, --password <PASSWORD>  Decompress or list with password
  -c, --threads <THREADS>    Concurrent working threads
  -h, --help                 Print help

NiceGuyIT avatar Aug 12 '25 00:08 NiceGuyIT