Skip to content

Commit 44fb75a

Browse files
authored
Smaller fixes (#795)
* Improve a little documentation, add missing bad extension * Allow to find the smallest files from CLo * Show error when all directories are reference folders * 2 more testing objects * Add missing original preset
1 parent 67db713 commit 44fb75a

16 files changed

+196
-38
lines changed

.github/workflows/mac.yml

-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ jobs:
4444
run: cargo build --release --features heif
4545
env:
4646
CARGO_INCREMENTAL: 0
47-
RUSTFLAGS: "-C debuginfo=0 -D warnings"
4847
if: ${{ matrix.type == 'release'}}
4948

5049
- name: Store MacOS CLI

Changelog.md

+7
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
## Version 5.0.1 - .08.2022r
2+
- Fixed problem with removing ending slash with empty disk window path
3+
- Added to CLI bad extensions mode
4+
- Fixed default sorting method in CLI where finding biggest files
5+
- Added tests to CI
6+
- Show error message when all directories are set as reference folders
7+
18
## Version 5.0.0 - 28.07.2022r
29
- GUI ported to use GTK 4 - [#466](https://github.com/qarmin/czkawka/pull/466)
310
- Use multithreading and improved algorithm to compare image hashes - [#762](https://github.com/qarmin/czkawka/pull/762)

README.md

+8
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,13 @@
2727

2828
![Czkawka](https://user-images.githubusercontent.com/41945903/145280350-506f7e94-4db0-4de7-a68d-6e7c26bbd2bf.gif)
2929

30+
## Supported OS
31+
Linux - Ubuntu 22.04+, Fedora 36+, Alpine Linux 3.16+, Debian 12+ and a lot of more
32+
Windows - 7, 8.1, 10, 11
33+
MacOS - 10.15+
34+
35+
If you are looking for older version that use GTK 3 and have support for more OS(like e.g. Ubuntu 20.04), look at [4.1.0](https://github.com/qarmin/czkawka/releases/tag/4.1.0) or older versions.
36+
3037
## How do I use it?
3138
You can find the instructions on how to use Czkawka [**here**](instructions/Instruction.md).
3239

@@ -140,6 +147,7 @@ You can help by creating:
140147
If the change is bigger, then it's a good idea to open a new issue to discuss changes, but issues with label `PR welcome` are already checked and accepted.
141148
- Documentation - There is an [instruction](instructions/Instruction.md) which you can improve.
142149
- Translations - Instruction how to translate files is available [here](instructions/Translations.md)
150+
- External contributions - App use big number of external libraries like [lofty](https://github.com/Serial-ATA/lofty-rs), [image-rs](https://github.com/image-rs/image) or [symphonia](https://github.com/pdeljanov/Symphonia) so improving this libraries will automatically improve Czkawka
143151

144152
You can also help by doing other things:
145153
- Creating text articles - [LinuxUprising](https://www.linuxuprising.com/2021/03/find-and-remove-duplicate-files-similar.html) or [Ubunlog](https://ubunlog.com/en/czkawka-finds-and-removes-empty-and-broken-duplicate-files/)

czkawka_cli/src/commands.rs

+32-7
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ pub enum Commands {
3636
file_to_save: FileToSave,
3737
#[clap(flatten)]
3838
not_recursive: NotRecursive,
39+
#[clap(flatten)]
40+
case_sensitive_name_comparison: CaseSensitiveNameComparison,
3941
#[cfg(target_family = "unix")]
4042
#[clap(flatten)]
4143
exclude_other_filesystems: ExcludeOtherFilesystems,
@@ -60,7 +62,7 @@ pub enum Commands {
6062
#[clap(flatten)]
6163
exclude_other_filesystems: ExcludeOtherFilesystems,
6264
},
63-
#[clap(name = "big", about = "Finds big files", help_message = HELP_MESSAGE, after_help = "EXAMPLE:\n czkawka big -d /home/rafal/ /home/piszczal -e /home/rafal/Roman -n 25 -x VIDEO -f results.txt")]
65+
#[clap(name = "big", about = "Finds big files", help_message = HELP_MESSAGE, after_help = "EXAMPLE:\n czkawka big -d /home/rafal/ /home/piszczal -e /home/rafal/Roman -n 25 -J -x VIDEO -f results.txt")]
6466
BiggestFiles {
6567
#[clap(flatten)]
6668
directories: Directories,
@@ -78,6 +80,8 @@ pub enum Commands {
7880
file_to_save: FileToSave,
7981
#[clap(flatten)]
8082
not_recursive: NotRecursive,
83+
#[clap(short = 'J', long, help = "Finds the smallest files instead the biggest")]
84+
smallest_mode: bool,
8185
#[cfg(target_family = "unix")]
8286
#[clap(flatten)]
8387
exclude_other_filesystems: ExcludeOtherFilesystems,
@@ -130,7 +134,7 @@ pub enum Commands {
130134
minimal_file_size: u64,
131135
#[clap(short = 'i', long, parse(try_from_str = parse_maximal_file_size), default_value = "18446744073709551615", help = "Maximum size in bytes", long_help = "Maximum size of checked files in bytes, assigning lower value may speed up searching")]
132136
maximal_file_size: u64,
133-
#[clap(short, long, default_value = "High", parse(try_from_str = parse_similar_images_similarity), help = "Similairty level (Minimal, VerySmall, Small, Medium, High, VeryHigh)", long_help = "Methods to choose similarity level of images which will be considered as duplicated.")]
137+
#[clap(short, long, default_value = "High", parse(try_from_str = parse_similar_images_similarity), help = "Similairty level (Minimal, VerySmall, Small, Medium, High, VeryHigh, Original)", long_help = "Methods to choose similarity level of images which will be considered as duplicated.")]
134138
similarity_preset: SimilarityPreset,
135139
#[clap(flatten)]
136140
excluded_items: ExcludedItems,
@@ -143,7 +147,7 @@ pub enum Commands {
143147
exclude_other_filesystems: ExcludeOtherFilesystems,
144148
#[clap(short = 'g', long, default_value = "Gradient", parse(try_from_str = parse_similar_hash_algorithm), help = "Hash algorithm (allowed: Mean, Gradient, Blockhash, VertGradient, DoubleGradient)")]
145149
hash_alg: HashAlg,
146-
#[clap(short = 'z', long, default_value = "Lanczos3", parse(try_from_str = parse_similar_image_filter), help = "Hash algorithm (allowed: Lanczos3, Nearest, Triangle, Faussian, Catmullrom)")]
150+
#[clap(short = 'z', long, default_value = "Nearest", parse(try_from_str = parse_similar_image_filter), help = "Hash algorithm (allowed: Lanczos3, Nearest, Triangle, Faussian, Catmullrom)")]
147151
image_filter: FilterType,
148152
#[clap(short = 'c', long, default_value = "16", parse(try_from_str = parse_image_hash_size), help = "Hash size (allowed: 8, 16, 32, 64)")]
149153
hash_size: u8,
@@ -238,11 +242,26 @@ pub enum Commands {
238242
#[clap(short = 't', long, parse(try_from_str = parse_tolerance), default_value = "10", help = "Video maximium difference (allowed values <0,20>)", long_help = "Maximum difference between video frames, bigger value means that videos can looks more and more different (allowed values <0,20>)")]
239243
tolerance: i32,
240244
},
241-
#[clap(name = "tester", about = "Contains various test", help_message = HELP_MESSAGE, after_help = "EXAMPLE:\n czkawka tests -i")]
242-
Tester {
243-
#[clap(short = 'i', long = "test_image", help = "Test speed of hashing provided test.jpg image with different filters and methods.")]
244-
test_image: bool,
245+
#[clap(name = "ext", about = "Finds files with invalid extensions", help_message = HELP_MESSAGE, after_help = "EXAMPLE:\n czkawka broken -d /home/czokolada/ -f results.txt")]
246+
BadExtensions {
247+
#[clap(flatten)]
248+
directories: Directories,
249+
#[clap(flatten)]
250+
excluded_directories: ExcludedDirectories,
251+
#[clap(flatten)]
252+
excluded_items: ExcludedItems,
253+
#[clap(flatten)]
254+
allowed_extensions: AllowedExtensions,
255+
#[clap(flatten)]
256+
file_to_save: FileToSave,
257+
#[clap(flatten)]
258+
not_recursive: NotRecursive,
259+
#[cfg(target_family = "unix")]
260+
#[clap(flatten)]
261+
exclude_other_filesystems: ExcludeOtherFilesystems,
245262
},
263+
#[clap(name = "tester", about = "Small utility to test supported speed of ", help_message = HELP_MESSAGE, after_help = "EXAMPLE:\n czkawka tester")]
264+
Tester {},
246265
}
247266

248267
#[derive(Debug, clap::StructOpt)]
@@ -317,6 +336,12 @@ pub struct AllowHardLinks {
317336
pub allow_hard_links: bool,
318337
}
319338

339+
#[derive(Debug, clap::StructOpt)]
340+
pub struct CaseSensitiveNameComparison {
341+
#[clap(short = 'l', long, help = "Use case sensitive name comparison")]
342+
pub case_sensitive_name_comparison: bool,
343+
}
344+
320345
#[derive(Debug, clap::StructOpt)]
321346
pub struct DryRun {
322347
#[clap(long, help = "Do nothing and print the operation that would happen.")]

czkawka_cli/src/main.rs

+43-7
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,18 @@ use std::process;
55
use clap::Parser;
66

77
use commands::Commands;
8+
use czkawka_core::big_file::SearchMode;
89
#[allow(unused_imports)] // It is used in release for print_results().
910
use czkawka_core::common_traits::*;
1011
use czkawka_core::similar_images::test_image_conversion_speed;
1112
use czkawka_core::{
13+
bad_extensions::BadExtensions,
1214
big_file::{self, BigFile},
1315
broken_files::{self, BrokenFiles},
1416
duplicate::DuplicateFinder,
1517
empty_files::{self, EmptyFiles},
1618
empty_folder::EmptyFolder,
17-
invalid_symlinks,
18-
invalid_symlinks::InvalidSymlinks,
19+
invalid_symlinks::{self, InvalidSymlinks},
1920
same_music::SameMusic,
2021
similar_images::{return_similarity_from_similarity_preset, SimilarImages},
2122
similar_videos::SimilarVideos,
@@ -49,6 +50,7 @@ fn main() {
4950
exclude_other_filesystems,
5051
allow_hard_links,
5152
dryrun,
53+
case_sensitive_name_comparison,
5254
} => {
5355
let mut df = DuplicateFinder::new();
5456

@@ -67,6 +69,7 @@ fn main() {
6769
df.set_exclude_other_filesystems(exclude_other_filesystems.exclude_other_filesystems);
6870
df.set_ignore_hard_links(!allow_hard_links.allow_hard_links);
6971
df.set_dryrun(dryrun.dryrun);
72+
df.set_case_sensitive_name_comparison(case_sensitive_name_comparison.case_sensitive_name_comparison);
7073

7174
df.find_duplicates(None, None);
7275

@@ -123,6 +126,7 @@ fn main() {
123126
#[cfg(target_family = "unix")]
124127
exclude_other_filesystems,
125128
delete_files,
129+
smallest_mode,
126130
} => {
127131
let mut bf = BigFile::new();
128132

@@ -137,6 +141,9 @@ fn main() {
137141
if delete_files {
138142
bf.set_delete_method(big_file::DeleteMethod::Delete);
139143
}
144+
if smallest_mode {
145+
bf.set_search_mode(SearchMode::SmallestFiles);
146+
}
140147

141148
bf.find_big_files(None, None);
142149

@@ -425,12 +432,41 @@ fn main() {
425432
vr.print_results();
426433
vr.get_text_messages().print_messages();
427434
}
428-
Commands::Tester { test_image } => {
429-
if test_image {
430-
test_image_conversion_speed();
431-
} else {
432-
println!("At least one test should be choosen!");
435+
Commands::BadExtensions {
436+
directories,
437+
excluded_directories,
438+
excluded_items,
439+
file_to_save,
440+
not_recursive,
441+
#[cfg(target_family = "unix")]
442+
exclude_other_filesystems,
443+
allowed_extensions,
444+
} => {
445+
let mut be = BadExtensions::new();
446+
447+
be.set_included_directory(directories.directories);
448+
be.set_excluded_directory(excluded_directories.excluded_directories);
449+
be.set_excluded_items(excluded_items.excluded_items);
450+
be.set_allowed_extensions(allowed_extensions.allowed_extensions.join(","));
451+
be.set_recursive_search(!not_recursive.not_recursive);
452+
#[cfg(target_family = "unix")]
453+
be.set_exclude_other_filesystems(exclude_other_filesystems.exclude_other_filesystems);
454+
455+
if let Some(file_name) = file_to_save.file_name() {
456+
if !be.save_results_to_file(file_name) {
457+
be.get_text_messages().print_messages();
458+
process::exit(1);
459+
}
433460
}
461+
462+
be.find_bad_extensions_files(None, None);
463+
464+
#[cfg(not(debug_assertions))] // This will show too much probably unnecessary data to debug, comment line only if needed
465+
be.print_results();
466+
be.get_text_messages().print_messages();
467+
}
468+
Commands::Tester {} => {
469+
test_image_conversion_speed();
434470
}
435471
}
436472
}

czkawka_core/src/bad_extensions.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -469,7 +469,7 @@ impl BadExtensions {
469469

470470
self.information.number_of_files_with_bad_extension = self.bad_extensions_files.len();
471471

472-
Common::print_time(system_time, SystemTime::now(), "sort_images - reading data from files in parallel".to_string());
472+
Common::print_time(system_time, SystemTime::now(), "bad extension finding".to_string());
473473

474474
// Clean unused data
475475
self.files_to_check = Default::default();
@@ -539,7 +539,7 @@ impl SaveResults for BadExtensions {
539539
if !self.bad_extensions_files.is_empty() {
540540
writeln!(writer, "Found {} files with invalid extension.", self.information.number_of_files_with_bad_extension).unwrap();
541541
for file_entry in self.bad_extensions_files.iter() {
542-
writeln!(writer, "{}", file_entry.path.display()).unwrap();
542+
writeln!(writer, "{} ----- {}", file_entry.path.display(), file_entry.proper_extensions).unwrap();
543543
}
544544
} else {
545545
write!(writer, "Not found any files with invalid extension.").unwrap();
@@ -556,7 +556,7 @@ impl PrintResults for BadExtensions {
556556
let start_time: SystemTime = SystemTime::now();
557557
println!("Found {} files with invalid extension.\n", self.information.number_of_files_with_bad_extension);
558558
for file_entry in self.bad_extensions_files.iter() {
559-
println!("{}", file_entry.path.display());
559+
println!("{} ----- {}", file_entry.path.display(), file_entry.proper_extensions);
560560
}
561561

562562
Common::print_time(start_time, SystemTime::now(), "print_entries".to_string());

czkawka_core/src/big_file.rs

+13-6
Original file line numberDiff line numberDiff line change
@@ -464,9 +464,12 @@ impl SaveResults for BigFile {
464464
}
465465

466466
if self.information.number_of_real_files != 0 {
467-
write!(writer, "{} the biggest files.\n\n", self.information.number_of_real_files).unwrap();
468-
469-
for (size, file_entry) in self.big_files.iter().rev() {
467+
if self.search_mode == SearchMode::BiggestFiles {
468+
write!(writer, "{} the biggest files.\n\n", self.information.number_of_real_files).unwrap();
469+
} else {
470+
write!(writer, "{} the smallest files.\n\n", self.information.number_of_real_files).unwrap();
471+
}
472+
for (size, file_entry) in self.big_files.iter() {
470473
writeln!(writer, "{} ({}) - {}", size.file_size(options::BINARY).unwrap(), size, file_entry.path.display()).unwrap();
471474
}
472475
} else {
@@ -480,9 +483,13 @@ impl SaveResults for BigFile {
480483
impl PrintResults for BigFile {
481484
fn print_results(&self) {
482485
let start_time: SystemTime = SystemTime::now();
483-
for (size, file_entry) in self.big_files.iter().rev() {
484-
// TODO Align all to same width
485-
println!("{} ({} bytes) - {}", size.file_size(options::BINARY).unwrap(), size, file_entry.path.display());
486+
if self.search_mode == SearchMode::BiggestFiles {
487+
println!("{} the biggest files.\n\n", self.information.number_of_real_files);
488+
} else {
489+
println!("{} the smallest files.\n\n", self.information.number_of_real_files);
490+
}
491+
for (size, file_entry) in self.big_files.iter() {
492+
println!("{} ({}) - {}", size.file_size(options::BINARY).unwrap(), size, file_entry.path.display());
486493
}
487494
Common::print_time(start_time, SystemTime::now(), "print_entries".to_string());
488495
}

czkawka_core/src/similar_images.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ use crate::flc;
3232
use crate::localizer_core::generate_translation_hashmap;
3333

3434
pub const SIMILAR_VALUES: [[u32; 6]; 4] = [
35-
[0, 2, 5, 7, 14, 20], // 8
35+
[1, 2, 5, 7, 14, 20], // 8
3636
[2, 5, 15, 30, 40, 40], // 16
3737
[4, 10, 20, 40, 40, 40], // 32
3838
[6, 20, 40, 40, 40, 40], // 64
@@ -59,6 +59,7 @@ pub struct FileEntry {
5959
/// Used by CLI tool when we cannot use directly values
6060
#[derive(Clone, Debug)]
6161
pub enum SimilarityPreset {
62+
Original,
6263
VeryHigh,
6364
High,
6465
Medium,
@@ -1283,6 +1284,7 @@ pub fn return_similarity_from_similarity_preset(similarity_preset: &SimilarityPr
12831284
_ => panic!(),
12841285
};
12851286
match similarity_preset {
1287+
SimilarityPreset::Original => 0,
12861288
SimilarityPreset::VeryHigh => SIMILAR_VALUES[index_preset][0],
12871289
SimilarityPreset::High => SIMILAR_VALUES[index_preset][1],
12881290
SimilarityPreset::Medium => SIMILAR_VALUES[index_preset][2],

czkawka_gui/i18n/en/czkawka_gui.ftl

+1
Original file line numberDiff line numberDiff line change
@@ -463,6 +463,7 @@ invalid_symlink_infinite_recursion = Infinite recursion
463463
invalid_symlink_non_existent_destination = Non-existent destination file
464464
465465
# Other
466+
selected_all_reference_folders = Cannot start search, when all directories are set as reference folders
466467
searching_for_data = Searching data, it may take a while, please wait...
467468
text_view_messages = MESSAGES
468469
text_view_warnings = WARNINGS

czkawka_gui/src/connect_things/connect_button_search.rs

+7
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,13 @@ pub fn connect_button_search(
117117
let check_button_settings_save_also_json = gui_data.settings.check_button_settings_save_also_json.clone();
118118

119119
buttons_search_clone.connect_clicked(move |_| {
120+
// Check if user selected all referenced folders
121+
let list_store_included_directories = get_list_store(&tree_view_included_directories);
122+
if check_if_list_store_column_have_all_same_values(&list_store_included_directories, ColumnsIncludedDirectory::ReferenceButton as i32, true) {
123+
entry_info.set_text(&flg!("selected_all_reference_folders"));
124+
return;
125+
}
126+
120127
let included_directories = get_path_buf_from_vector_of_strings(get_string_from_list_store(&tree_view_included_directories, ColumnsIncludedDirectory::Path as i32, None));
121128
let excluded_directories = get_path_buf_from_vector_of_strings(get_string_from_list_store(&tree_view_excluded_directories, ColumnsExcludedDirectory::Path as i32, None));
122129
let reference_directories = get_path_buf_from_vector_of_strings(get_string_from_list_store(

czkawka_gui/src/connect_things/connect_selection_of_directories.rs

+10
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ fn add_manually_directories(window_main: &Window, tree_view: &TreeView, excluded
184184
dialog.close();
185185
});
186186
}
187+
187188
fn remove_ending_slashes(original_string: &mut String) {
188189
let mut windows_disk_path: bool = false;
189190
let mut chars = original_string.chars();
@@ -202,6 +203,7 @@ fn remove_ending_slashes(original_string: &mut String) {
202203
original_string.pop();
203204
}
204205
}
206+
205207
#[test]
206208
pub fn test_remove_ending_slashes() {
207209
let mut original = "/home/rafal".to_string();
@@ -248,6 +250,14 @@ pub fn test_remove_ending_slashes() {
248250
remove_ending_slashes(&mut original);
249251
assert_eq!(&original, "C:/");
250252

253+
let mut original = "C:/roman/function/".to_string();
254+
remove_ending_slashes(&mut original);
255+
assert_eq!(&original, "C:/roman/function");
256+
257+
let mut original = "C:/staszek/without".to_string();
258+
remove_ending_slashes(&mut original);
259+
assert_eq!(&original, "C:/staszek/without");
260+
251261
let mut original = "C:\\\\\\\\\\".to_string();
252262
remove_ending_slashes(&mut original);
253263
assert_eq!(&original, "C:\\");

0 commit comments

Comments
 (0)