diff --git a/.github/workflows/mac.yml b/.github/workflows/mac.yml index a4632cb..3eff5c5 100644 --- a/.github/workflows/mac.yml +++ b/.github/workflows/mac.yml @@ -44,7 +44,6 @@ jobs: run: cargo build --release --features heif env: CARGO_INCREMENTAL: 0 - RUSTFLAGS: "-C debuginfo=0 -D warnings" if: ${{ matrix.type == 'release'}} - name: Store MacOS CLI diff --git a/Changelog.md b/Changelog.md index 3b54cfe..1325d8b 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,3 +1,10 @@ +## Version 5.0.1 - .08.2022r +- Fixed problem with removing ending slash with empty disk window path +- Added to CLI bad extensions mode +- Fixed default sorting method in CLI where finding biggest files +- Added tests to CI +- Show error message when all directories are set as reference folders + ## Version 5.0.0 - 28.07.2022r - GUI ported to use GTK 4 - [#466](https://github.com/qarmin/czkawka/pull/466) - Use multithreading and improved algorithm to compare image hashes - [#762](https://github.com/qarmin/czkawka/pull/762) diff --git a/README.md b/README.md index 3fa6456..cf8ecb9 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,13 @@ ![Czkawka](https://user-images.githubusercontent.com/41945903/145280350-506f7e94-4db0-4de7-a68d-6e7c26bbd2bf.gif) +## Supported OS +Linux - Ubuntu 22.04+, Fedora 36+, Alpine Linux 3.16+, Debian 12+ and a lot of more +Windows - 7, 8.1, 10, 11 +MacOS - 10.15+ + +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. + ## How do I use it? You can find the instructions on how to use Czkawka [**here**](instructions/Instruction.md). @@ -140,6 +147,7 @@ You can help by creating: 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. - Documentation - There is an [instruction](instructions/Instruction.md) which you can improve. - Translations - Instruction how to translate files is available [here](instructions/Translations.md) +- 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 You can also help by doing other things: - 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/) diff --git a/czkawka_cli/src/commands.rs b/czkawka_cli/src/commands.rs index 7cebd00..16791a6 100644 --- a/czkawka_cli/src/commands.rs +++ b/czkawka_cli/src/commands.rs @@ -36,6 +36,8 @@ pub enum Commands { file_to_save: FileToSave, #[clap(flatten)] not_recursive: NotRecursive, + #[clap(flatten)] + case_sensitive_name_comparison: CaseSensitiveNameComparison, #[cfg(target_family = "unix")] #[clap(flatten)] exclude_other_filesystems: ExcludeOtherFilesystems, @@ -60,7 +62,7 @@ pub enum Commands { #[clap(flatten)] exclude_other_filesystems: ExcludeOtherFilesystems, }, - #[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")] + #[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")] BiggestFiles { #[clap(flatten)] directories: Directories, @@ -78,6 +80,8 @@ pub enum Commands { file_to_save: FileToSave, #[clap(flatten)] not_recursive: NotRecursive, + #[clap(short = 'J', long, help = "Finds the smallest files instead the biggest")] + smallest_mode: bool, #[cfg(target_family = "unix")] #[clap(flatten)] exclude_other_filesystems: ExcludeOtherFilesystems, @@ -130,7 +134,7 @@ pub enum Commands { minimal_file_size: u64, #[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")] maximal_file_size: u64, - #[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.")] + #[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.")] similarity_preset: SimilarityPreset, #[clap(flatten)] excluded_items: ExcludedItems, @@ -143,7 +147,7 @@ pub enum Commands { exclude_other_filesystems: ExcludeOtherFilesystems, #[clap(short = 'g', long, default_value = "Gradient", parse(try_from_str = parse_similar_hash_algorithm), help = "Hash algorithm (allowed: Mean, Gradient, Blockhash, VertGradient, DoubleGradient)")] hash_alg: HashAlg, - #[clap(short = 'z', long, default_value = "Lanczos3", parse(try_from_str = parse_similar_image_filter), help = "Hash algorithm (allowed: Lanczos3, Nearest, Triangle, Faussian, Catmullrom)")] + #[clap(short = 'z', long, default_value = "Nearest", parse(try_from_str = parse_similar_image_filter), help = "Hash algorithm (allowed: Lanczos3, Nearest, Triangle, Faussian, Catmullrom)")] image_filter: FilterType, #[clap(short = 'c', long, default_value = "16", parse(try_from_str = parse_image_hash_size), help = "Hash size (allowed: 8, 16, 32, 64)")] hash_size: u8, @@ -238,11 +242,26 @@ pub enum Commands { #[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>)")] tolerance: i32, }, - #[clap(name = "tester", about = "Contains various test", help_message = HELP_MESSAGE, after_help = "EXAMPLE:\n czkawka tests -i")] - Tester { - #[clap(short = 'i', long = "test_image", help = "Test speed of hashing provided test.jpg image with different filters and methods.")] - test_image: bool, + #[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")] + BadExtensions { + #[clap(flatten)] + directories: Directories, + #[clap(flatten)] + excluded_directories: ExcludedDirectories, + #[clap(flatten)] + excluded_items: ExcludedItems, + #[clap(flatten)] + allowed_extensions: AllowedExtensions, + #[clap(flatten)] + file_to_save: FileToSave, + #[clap(flatten)] + not_recursive: NotRecursive, + #[cfg(target_family = "unix")] + #[clap(flatten)] + exclude_other_filesystems: ExcludeOtherFilesystems, }, + #[clap(name = "tester", about = "Small utility to test supported speed of ", help_message = HELP_MESSAGE, after_help = "EXAMPLE:\n czkawka tester")] + Tester {}, } #[derive(Debug, clap::StructOpt)] @@ -317,6 +336,12 @@ pub struct AllowHardLinks { pub allow_hard_links: bool, } +#[derive(Debug, clap::StructOpt)] +pub struct CaseSensitiveNameComparison { + #[clap(short = 'l', long, help = "Use case sensitive name comparison")] + pub case_sensitive_name_comparison: bool, +} + #[derive(Debug, clap::StructOpt)] pub struct DryRun { #[clap(long, help = "Do nothing and print the operation that would happen.")] diff --git a/czkawka_cli/src/main.rs b/czkawka_cli/src/main.rs index 08c3f09..2101bdd 100644 --- a/czkawka_cli/src/main.rs +++ b/czkawka_cli/src/main.rs @@ -5,17 +5,18 @@ use std::process; use clap::Parser; use commands::Commands; +use czkawka_core::big_file::SearchMode; #[allow(unused_imports)] // It is used in release for print_results(). use czkawka_core::common_traits::*; use czkawka_core::similar_images::test_image_conversion_speed; use czkawka_core::{ + bad_extensions::BadExtensions, big_file::{self, BigFile}, broken_files::{self, BrokenFiles}, duplicate::DuplicateFinder, empty_files::{self, EmptyFiles}, empty_folder::EmptyFolder, - invalid_symlinks, - invalid_symlinks::InvalidSymlinks, + invalid_symlinks::{self, InvalidSymlinks}, same_music::SameMusic, similar_images::{return_similarity_from_similarity_preset, SimilarImages}, similar_videos::SimilarVideos, @@ -49,6 +50,7 @@ fn main() { exclude_other_filesystems, allow_hard_links, dryrun, + case_sensitive_name_comparison, } => { let mut df = DuplicateFinder::new(); @@ -67,6 +69,7 @@ fn main() { df.set_exclude_other_filesystems(exclude_other_filesystems.exclude_other_filesystems); df.set_ignore_hard_links(!allow_hard_links.allow_hard_links); df.set_dryrun(dryrun.dryrun); + df.set_case_sensitive_name_comparison(case_sensitive_name_comparison.case_sensitive_name_comparison); df.find_duplicates(None, None); @@ -123,6 +126,7 @@ fn main() { #[cfg(target_family = "unix")] exclude_other_filesystems, delete_files, + smallest_mode, } => { let mut bf = BigFile::new(); @@ -137,6 +141,9 @@ fn main() { if delete_files { bf.set_delete_method(big_file::DeleteMethod::Delete); } + if smallest_mode { + bf.set_search_mode(SearchMode::SmallestFiles); + } bf.find_big_files(None, None); @@ -425,12 +432,41 @@ fn main() { vr.print_results(); vr.get_text_messages().print_messages(); } - Commands::Tester { test_image } => { - if test_image { - test_image_conversion_speed(); - } else { - println!("At least one test should be choosen!"); + Commands::BadExtensions { + directories, + excluded_directories, + excluded_items, + file_to_save, + not_recursive, + #[cfg(target_family = "unix")] + exclude_other_filesystems, + allowed_extensions, + } => { + let mut be = BadExtensions::new(); + + be.set_included_directory(directories.directories); + be.set_excluded_directory(excluded_directories.excluded_directories); + be.set_excluded_items(excluded_items.excluded_items); + be.set_allowed_extensions(allowed_extensions.allowed_extensions.join(",")); + be.set_recursive_search(!not_recursive.not_recursive); + #[cfg(target_family = "unix")] + be.set_exclude_other_filesystems(exclude_other_filesystems.exclude_other_filesystems); + + if let Some(file_name) = file_to_save.file_name() { + if !be.save_results_to_file(file_name) { + be.get_text_messages().print_messages(); + process::exit(1); + } } + + be.find_bad_extensions_files(None, None); + + #[cfg(not(debug_assertions))] // This will show too much probably unnecessary data to debug, comment line only if needed + be.print_results(); + be.get_text_messages().print_messages(); + } + Commands::Tester {} => { + test_image_conversion_speed(); } } } diff --git a/czkawka_core/src/bad_extensions.rs b/czkawka_core/src/bad_extensions.rs index 184f4d2..973de9a 100644 --- a/czkawka_core/src/bad_extensions.rs +++ b/czkawka_core/src/bad_extensions.rs @@ -469,7 +469,7 @@ impl BadExtensions { self.information.number_of_files_with_bad_extension = self.bad_extensions_files.len(); - Common::print_time(system_time, SystemTime::now(), "sort_images - reading data from files in parallel".to_string()); + Common::print_time(system_time, SystemTime::now(), "bad extension finding".to_string()); // Clean unused data self.files_to_check = Default::default(); @@ -539,7 +539,7 @@ impl SaveResults for BadExtensions { if !self.bad_extensions_files.is_empty() { writeln!(writer, "Found {} files with invalid extension.", self.information.number_of_files_with_bad_extension).unwrap(); for file_entry in self.bad_extensions_files.iter() { - writeln!(writer, "{}", file_entry.path.display()).unwrap(); + writeln!(writer, "{} ----- {}", file_entry.path.display(), file_entry.proper_extensions).unwrap(); } } else { write!(writer, "Not found any files with invalid extension.").unwrap(); @@ -556,7 +556,7 @@ impl PrintResults for BadExtensions { let start_time: SystemTime = SystemTime::now(); println!("Found {} files with invalid extension.\n", self.information.number_of_files_with_bad_extension); for file_entry in self.bad_extensions_files.iter() { - println!("{}", file_entry.path.display()); + println!("{} ----- {}", file_entry.path.display(), file_entry.proper_extensions); } Common::print_time(start_time, SystemTime::now(), "print_entries".to_string()); diff --git a/czkawka_core/src/big_file.rs b/czkawka_core/src/big_file.rs index c72ebc1..26b24a6 100644 --- a/czkawka_core/src/big_file.rs +++ b/czkawka_core/src/big_file.rs @@ -464,9 +464,12 @@ impl SaveResults for BigFile { } if self.information.number_of_real_files != 0 { - write!(writer, "{} the biggest files.\n\n", self.information.number_of_real_files).unwrap(); - - for (size, file_entry) in self.big_files.iter().rev() { + if self.search_mode == SearchMode::BiggestFiles { + write!(writer, "{} the biggest files.\n\n", self.information.number_of_real_files).unwrap(); + } else { + write!(writer, "{} the smallest files.\n\n", self.information.number_of_real_files).unwrap(); + } + for (size, file_entry) in self.big_files.iter() { writeln!(writer, "{} ({}) - {}", size.file_size(options::BINARY).unwrap(), size, file_entry.path.display()).unwrap(); } } else { @@ -480,9 +483,13 @@ impl SaveResults for BigFile { impl PrintResults for BigFile { fn print_results(&self) { let start_time: SystemTime = SystemTime::now(); - for (size, file_entry) in self.big_files.iter().rev() { - // TODO Align all to same width - println!("{} ({} bytes) - {}", size.file_size(options::BINARY).unwrap(), size, file_entry.path.display()); + if self.search_mode == SearchMode::BiggestFiles { + println!("{} the biggest files.\n\n", self.information.number_of_real_files); + } else { + println!("{} the smallest files.\n\n", self.information.number_of_real_files); + } + for (size, file_entry) in self.big_files.iter() { + println!("{} ({}) - {}", size.file_size(options::BINARY).unwrap(), size, file_entry.path.display()); } Common::print_time(start_time, SystemTime::now(), "print_entries".to_string()); } diff --git a/czkawka_core/src/similar_images.rs b/czkawka_core/src/similar_images.rs index c9d59c9..60a2189 100644 --- a/czkawka_core/src/similar_images.rs +++ b/czkawka_core/src/similar_images.rs @@ -32,7 +32,7 @@ use crate::flc; use crate::localizer_core::generate_translation_hashmap; pub const SIMILAR_VALUES: [[u32; 6]; 4] = [ - [0, 2, 5, 7, 14, 20], // 8 + [1, 2, 5, 7, 14, 20], // 8 [2, 5, 15, 30, 40, 40], // 16 [4, 10, 20, 40, 40, 40], // 32 [6, 20, 40, 40, 40, 40], // 64 @@ -59,6 +59,7 @@ pub struct FileEntry { /// Used by CLI tool when we cannot use directly values #[derive(Clone, Debug)] pub enum SimilarityPreset { + Original, VeryHigh, High, Medium, @@ -1283,6 +1284,7 @@ pub fn return_similarity_from_similarity_preset(similarity_preset: &SimilarityPr _ => panic!(), }; match similarity_preset { + SimilarityPreset::Original => 0, SimilarityPreset::VeryHigh => SIMILAR_VALUES[index_preset][0], SimilarityPreset::High => SIMILAR_VALUES[index_preset][1], SimilarityPreset::Medium => SIMILAR_VALUES[index_preset][2], diff --git a/czkawka_gui/i18n/en/czkawka_gui.ftl b/czkawka_gui/i18n/en/czkawka_gui.ftl index 5b89c87..7879711 100644 --- a/czkawka_gui/i18n/en/czkawka_gui.ftl +++ b/czkawka_gui/i18n/en/czkawka_gui.ftl @@ -463,6 +463,7 @@ invalid_symlink_infinite_recursion = Infinite recursion invalid_symlink_non_existent_destination = Non-existent destination file # Other +selected_all_reference_folders = Cannot start search, when all directories are set as reference folders searching_for_data = Searching data, it may take a while, please wait... text_view_messages = MESSAGES text_view_warnings = WARNINGS diff --git a/czkawka_gui/src/connect_things/connect_button_search.rs b/czkawka_gui/src/connect_things/connect_button_search.rs index fc87410..c7a46c0 100644 --- a/czkawka_gui/src/connect_things/connect_button_search.rs +++ b/czkawka_gui/src/connect_things/connect_button_search.rs @@ -117,6 +117,13 @@ pub fn connect_button_search( let check_button_settings_save_also_json = gui_data.settings.check_button_settings_save_also_json.clone(); buttons_search_clone.connect_clicked(move |_| { + // Check if user selected all referenced folders + let list_store_included_directories = get_list_store(&tree_view_included_directories); + if check_if_list_store_column_have_all_same_values(&list_store_included_directories, ColumnsIncludedDirectory::ReferenceButton as i32, true) { + entry_info.set_text(&flg!("selected_all_reference_folders")); + return; + } + let included_directories = get_path_buf_from_vector_of_strings(get_string_from_list_store(&tree_view_included_directories, ColumnsIncludedDirectory::Path as i32, None)); let excluded_directories = get_path_buf_from_vector_of_strings(get_string_from_list_store(&tree_view_excluded_directories, ColumnsExcludedDirectory::Path as i32, None)); let reference_directories = get_path_buf_from_vector_of_strings(get_string_from_list_store( diff --git a/czkawka_gui/src/connect_things/connect_selection_of_directories.rs b/czkawka_gui/src/connect_things/connect_selection_of_directories.rs index 3829982..1ad1782 100644 --- a/czkawka_gui/src/connect_things/connect_selection_of_directories.rs +++ b/czkawka_gui/src/connect_things/connect_selection_of_directories.rs @@ -184,6 +184,7 @@ fn add_manually_directories(window_main: &Window, tree_view: &TreeView, excluded dialog.close(); }); } + fn remove_ending_slashes(original_string: &mut String) { let mut windows_disk_path: bool = false; let mut chars = original_string.chars(); @@ -202,6 +203,7 @@ fn remove_ending_slashes(original_string: &mut String) { original_string.pop(); } } + #[test] pub fn test_remove_ending_slashes() { let mut original = "/home/rafal".to_string(); @@ -248,6 +250,14 @@ pub fn test_remove_ending_slashes() { remove_ending_slashes(&mut original); assert_eq!(&original, "C:/"); + let mut original = "C:/roman/function/".to_string(); + remove_ending_slashes(&mut original); + assert_eq!(&original, "C:/roman/function"); + + let mut original = "C:/staszek/without".to_string(); + remove_ending_slashes(&mut original); + assert_eq!(&original, "C:/staszek/without"); + let mut original = "C:\\\\\\\\\\".to_string(); remove_ending_slashes(&mut original); assert_eq!(&original, "C:\\"); diff --git a/czkawka_gui/src/help_functions.rs b/czkawka_gui/src/help_functions.rs index ccfb2b1..bdcef14 100644 --- a/czkawka_gui/src/help_functions.rs +++ b/czkawka_gui/src/help_functions.rs @@ -743,6 +743,24 @@ pub fn check_if_value_is_in_list_store(list_store: &ListStore, column: i32, valu false } +pub fn check_if_list_store_column_have_all_same_values(list_store: &ListStore, column: i32, value: bool) -> bool { + if let Some(iter) = list_store.iter_first() { + loop { + let list_store_value: bool = list_store.get::(&iter, column as i32); + + if value != list_store_value { + return false; + } + + if !list_store.iter_next(&iter) { + break; + } + } + return true; + } + false +} + #[cfg(test)] mod test { use gtk4::prelude::*; @@ -750,9 +768,44 @@ mod test { use image::DynamicImage; use crate::help_functions::{ - change_dimension_to_krotka, check_if_value_is_in_list_store, get_all_boxes_from_widget, get_all_direct_children, get_max_file_name, get_pixbuf_from_dynamic_image, + change_dimension_to_krotka, check_if_list_store_column_have_all_same_values, check_if_value_is_in_list_store, get_all_boxes_from_widget, get_all_direct_children, + get_max_file_name, get_pixbuf_from_dynamic_image, }; + #[gtk4::test] + fn test_check_if_list_store_column_have_all_same_values() { + let columns_types: &[glib::types::Type] = &[glib::types::Type::BOOL]; + let list_store = gtk4::ListStore::new(columns_types); + + list_store.clear(); + let values_to_add: &[(u32, &dyn ToValue)] = &[(0, &true), (0, &true), (0, &false)]; + for i in values_to_add { + list_store.set(&list_store.append(), &[*i]); + } + assert!(!check_if_list_store_column_have_all_same_values(&list_store, 0, true)); + assert!(!check_if_list_store_column_have_all_same_values(&list_store, 0, false)); + + list_store.clear(); + let values_to_add: &[(u32, &dyn ToValue)] = &[(0, &true), (0, &true), (0, &true)]; + for i in values_to_add { + list_store.set(&list_store.append(), &[*i]); + } + assert!(check_if_list_store_column_have_all_same_values(&list_store, 0, true)); + assert!(!check_if_list_store_column_have_all_same_values(&list_store, 0, false)); + + list_store.clear(); + let values_to_add: &[(u32, &dyn ToValue)] = &[(0, &false)]; + for i in values_to_add { + list_store.set(&list_store.append(), &[*i]); + } + assert!(!check_if_list_store_column_have_all_same_values(&list_store, 0, true)); + assert!(check_if_list_store_column_have_all_same_values(&list_store, 0, false)); + + list_store.clear(); + assert!(!check_if_list_store_column_have_all_same_values(&list_store, 0, true)); + assert!(!check_if_list_store_column_have_all_same_values(&list_store, 0, false)); + } + #[gtk4::test] fn test_check_if_value_is_in_list_store() { let columns_types: &[glib::types::Type] = &[glib::types::Type::STRING]; @@ -808,6 +861,7 @@ mod test { get_pixbuf_from_dynamic_image(&dynamic_image).unwrap(); get_pixbuf_from_dynamic_image(&dynamic_image).unwrap(); } + #[test] fn test_change_dimension_to_krotka() { assert_eq!(change_dimension_to_krotka("50x50".to_string()), (50, 50)); diff --git a/czkawka_gui/ui/settings.ui b/czkawka_gui/ui/settings.ui index 60987dd..cbce0c9 100644 --- a/czkawka_gui/ui/settings.ui +++ b/czkawka_gui/ui/settings.ui @@ -153,7 +153,7 @@ 1 1 - Hide hard links(only Linux and MacOS) + Hide hard links(only Linux and macOS) diff --git a/data/com.github.qarmin.czkawka.metainfo.xml b/data/com.github.qarmin.czkawka.metainfo.xml index 005bf98..e11364f 100644 --- a/data/com.github.qarmin.czkawka.metainfo.xml +++ b/data/com.github.qarmin.czkawka.metainfo.xml @@ -19,7 +19,7 @@ - + RafaƂ Mikrut diff --git a/instructions/Compilation.md b/instructions/Compilation.md index 62244dc..22b6cb1 100644 --- a/instructions/Compilation.md +++ b/instructions/Compilation.md @@ -11,8 +11,8 @@ Support for heif images is optional and require to install libheif library. | Program | Min | What for | |---------|------|-------------------------------------------------------------------------------| -| Rust | 1.60 | Czkawka, aims to support the latest available version of Rust on Ubuntu 20.04 | -| GTK | 3.24 | Only for the `GTK` backend | +| Rust | 1.60 | Czkawka, aims to support the latest available version of Rust on Ubuntu 22.04 | +| GTK | 4.6 | Only for the `GTK` backend | #### Debian / Ubuntu ```shell @@ -24,11 +24,11 @@ sudo apt install -y libgtk-4-dev #### Fedora / CentOS / Rocky Linux ```shell curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh # Download the latest stable Rust -sudo yum install gtk3-devel glib2-devel +sudo yum install gtk4-devel glib2-devel ``` #### macOS -You need to install Rust via Homebrew, GTK Libraries and optionally heif library(to have support for heic files, which are quite popular on mac) +You need to install Rust via Homebrew, GTK Libraries and optionally heif library(to have support for heic files, which are quite popular on Mac) ```shell /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" brew install rustup @@ -88,10 +88,9 @@ target/release/czkawka_gui ``` ## Additional features -For now, finding broken audio files is temporarily disabled by default, because app crashes when audio libraries are not found on the computer. -I'm waiting for ability to disable audio playback feature, so after that I will be able to re-enable by default this feature (https://github.com/RustAudio/rodio/issues/349) +Currently, the only additional dependence is heif image support. -To enable checking for broken audio files, just add ` --all-features` +To enable checking for heif images, just add ` --all-features` or `--features heif` ``` -cargo run --all-features --bin czkawka_cli -- broken -d /home/rafal/ -f "results.txt" +cargo run --features heif --bin czkawka_cli -- image -d /home/rafal/ -f "results.txt" ``` diff --git a/instructions/Installation.md b/instructions/Installation.md index 05416b1..013e49e 100644 --- a/instructions/Installation.md +++ b/instructions/Installation.md @@ -7,13 +7,16 @@ For Czkawka GUI the lowest supported version of GTK is `3.24` which is the only In app exists Similar Video tool which require `FFmpeg` to work, but is completelly optional and without it, only warning would be printed when trying to use this tool without installed ffmpeg. Broken files finder by default don't check for music files, but it is possible to enable this feature and that require to have alsa lib installed(on Ubuntu this is `libasound2-dev` package) +**Warning** +Main Czkawka GUI dependency - GTK 4 is only available on newer systems like e.g. Ubuntu 22.04, so if you have problems with running app on older systems, you may like to use older Czkawka versions, upgrade OS or install flatpak package which use its own set of dependencies. + #### Ubuntu/Debian/Linux Mint ``` sudo apt install libgtk-4-dev ffmpeg ``` #### Fedora/Rocky Linux ``` -sudo yum install gtk3-devel glib2-devel +sudo yum install gtk4-devel glib2-devel sudo dnf -y install https://download1.rpmfusion.org/free/fedora/rpmfusion-free-release-$(rpm -E %fedora).noarch.rpm sudo dnf -y install https://download1.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-$(rpm -E %fedora).noarch.rpm sudo dnf -y install ffmpeg @@ -43,7 +46,7 @@ At the end execute it: **Warning** Prebuilt binaries are available only for x86_64, so if you use ARM machine like e.g. Mac M1, you need to compile manually app. -There is also a way to use x86_64 binaries on ARM, but this require to install special version of required libraries probably via: +There is also a way to use x86_64 binaries on ARM, but this requires to install special version of required libraries probably via: ```shell arch -x86_64 /usr/local/bin/brew install gtk4 adwaita-icon-theme ffmpeg librsvg libheif ```