Skip to content

Commit 373954c

Browse files
committed
Up
1 parent 944e6ac commit 373954c

9 files changed

Lines changed: 131 additions & 90 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

czkawka_cli/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ czkawka_core = { path = "../czkawka_core", version = "8.0.0", features = [] }
2020
indicatif = "0.17"
2121
crossbeam-channel = { version = "0.5", features = [] }
2222
ctrlc = { version = "3.4", features = ["termination"] }
23+
humansize = "2.1"
2324

2425
[features]
2526
default = ["fast_image_resize"]

czkawka_cli/src/commands.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -80,12 +80,6 @@ pub enum Commands {
8080
after_help = "EXAMPLE:\n czkawka ext -d /home/czokolada/ -f results.txt"
8181
)]
8282
BadExtensions(BadExtensionsArgs),
83-
#[clap(
84-
name = "tester",
85-
about = "Small utility to test supported speed of converting images",
86-
after_help = "EXAMPLE:\n czkawka tester"
87-
)]
88-
Tester,
8983
}
9084

9185
#[derive(Debug, clap::Args)]
@@ -486,6 +480,16 @@ pub struct CommonCliItems {
486480
#[cfg(target_family = "unix")]
487481
#[clap(short = 'X', long, help = "Exclude files on other filesystems")]
488482
pub exclude_other_filesystems: bool,
483+
#[clap(flatten)]
484+
pub do_not_print: DoNotPrint,
485+
}
486+
487+
#[derive(Debug, clap::Args)]
488+
pub struct DoNotPrint {
489+
#[clap(short = 'N', long, help = "Do not print the results to the console")]
490+
pub do_not_print_results: bool,
491+
#[clap(short = 'M', long, help = "Do not print info/warnings/errors from the program to console")]
492+
pub do_not_print_messages: bool,
489493
}
490494

491495
#[derive(Debug, clap::Args)]

czkawka_cli/src/main.rs

Lines changed: 72 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use czkawka_core::tools::empty_files::EmptyFiles;
2222
use czkawka_core::tools::empty_folder::EmptyFolder;
2323
use czkawka_core::tools::invalid_symlinks::InvalidSymlinks;
2424
use czkawka_core::tools::same_music::{SameMusic, SameMusicParameters};
25-
use czkawka_core::tools::similar_images::{SimilarImages, SimilarImagesParameters, return_similarity_from_similarity_preset, test_image_conversion_speed};
25+
use czkawka_core::tools::similar_images::{SimilarImages, SimilarImagesParameters, return_similarity_from_similarity_preset};
2626
use czkawka_core::tools::similar_videos::{SimilarVideos, SimilarVideosParameters};
2727
use czkawka_core::tools::temporary::Temporary;
2828
use log::error;
@@ -51,24 +51,34 @@ fn main() {
5151
let stop_flag = Arc::new(AtomicBool::new(false));
5252
let store_flag_cloned = stop_flag.clone();
5353

54+
let found_any_files = Arc::new(AtomicBool::new(false));
55+
let found_any_files_clone = found_any_files.clone();
56+
5457
let calculate_thread = thread::Builder::new()
5558
.stack_size(DEFAULT_THREAD_SIZE)
56-
.spawn(move || match command {
57-
Commands::Duplicates(duplicates_args) => duplicates(duplicates_args, &stop_flag, &progress_sender),
58-
Commands::EmptyFolders(empty_folders_args) => empty_folders(empty_folders_args, &stop_flag, &progress_sender),
59-
Commands::BiggestFiles(biggest_files_args) => biggest_files(biggest_files_args, &stop_flag, &progress_sender),
60-
Commands::EmptyFiles(empty_files_args) => empty_files(empty_files_args, &stop_flag, &progress_sender),
61-
Commands::Temporary(temporary_args) => temporary(temporary_args, &stop_flag, &progress_sender),
62-
Commands::SimilarImages(similar_images_args) => similar_images(similar_images_args, &stop_flag, &progress_sender),
63-
Commands::SameMusic(same_music_args) => same_music(same_music_args, &stop_flag, &progress_sender),
64-
Commands::InvalidSymlinks(invalid_symlinks_args) => invalid_symlinks(invalid_symlinks_args, &stop_flag, &progress_sender),
65-
Commands::BrokenFiles(broken_files_args) => broken_files(broken_files_args, &stop_flag, &progress_sender),
66-
Commands::SimilarVideos(similar_videos_args) => similar_videos(similar_videos_args, &stop_flag, &progress_sender),
67-
Commands::BadExtensions(bad_extensions_args) => bad_extensions(bad_extensions_args, &stop_flag, &progress_sender),
68-
Commands::Tester => test_image_conversion_speed(),
59+
.spawn(move || {
60+
let found_files = match command {
61+
Commands::Duplicates(duplicates_args) => duplicates(duplicates_args, &stop_flag, &progress_sender),
62+
Commands::EmptyFolders(empty_folders_args) => empty_folders(empty_folders_args, &stop_flag, &progress_sender),
63+
Commands::BiggestFiles(biggest_files_args) => biggest_files(biggest_files_args, &stop_flag, &progress_sender),
64+
Commands::EmptyFiles(empty_files_args) => empty_files(empty_files_args, &stop_flag, &progress_sender),
65+
Commands::Temporary(temporary_args) => temporary(temporary_args, &stop_flag, &progress_sender),
66+
Commands::SimilarImages(similar_images_args) => similar_images(similar_images_args, &stop_flag, &progress_sender),
67+
Commands::SameMusic(same_music_args) => same_music(same_music_args, &stop_flag, &progress_sender),
68+
Commands::InvalidSymlinks(invalid_symlinks_args) => invalid_symlinks(invalid_symlinks_args, &stop_flag, &progress_sender),
69+
Commands::BrokenFiles(broken_files_args) => broken_files(broken_files_args, &stop_flag, &progress_sender),
70+
Commands::SimilarVideos(similar_videos_args) => similar_videos(similar_videos_args, &stop_flag, &progress_sender),
71+
Commands::BadExtensions(bad_extensions_args) => bad_extensions(bad_extensions_args, &stop_flag, &progress_sender),
72+
};
73+
74+
found_any_files_clone.store(found_files, std::sync::atomic::Ordering::SeqCst);
6975
})
7076
.expect("Failed to spawn calculation thread");
77+
7178
ctrlc::set_handler(move || {
79+
if store_flag_cloned.load(std::sync::atomic::Ordering::SeqCst) {
80+
return;
81+
}
7282
println!("Get Ctrl+C signal, stopping...");
7383
store_flag_cloned.store(true, std::sync::atomic::Ordering::SeqCst);
7484
})
@@ -77,9 +87,15 @@ fn main() {
7787
connect_progress(&progress_receiver);
7888

7989
calculate_thread.join().expect("Failed to join calculation thread");
90+
91+
if found_any_files.load(std::sync::atomic::Ordering::SeqCst) {
92+
std::process::exit(0);
93+
} else {
94+
std::process::exit(1);
95+
}
8096
}
8197

82-
fn duplicates(duplicates: DuplicatesArgs, stop_flag: &Arc<AtomicBool>, progress_sender: &Sender<ProgressData>) {
98+
fn duplicates(duplicates: DuplicatesArgs, stop_flag: &Arc<AtomicBool>, progress_sender: &Sender<ProgressData>) -> bool {
8399
let DuplicatesArgs {
84100
common_cli_items,
85101
reference_directories,
@@ -116,9 +132,14 @@ fn duplicates(duplicates: DuplicatesArgs, stop_flag: &Arc<AtomicBool>, progress_
116132
item.find_duplicates(Some(stop_flag), Some(progress_sender));
117133

118134
save_and_print_results(&item, &common_cli_items);
135+
136+
item.get_information().number_of_duplicated_files_by_hash > 0
137+
|| item.get_information().number_of_duplicated_files_by_name > 0
138+
|| item.get_information().number_of_duplicated_files_by_size > 0
139+
|| item.get_information().number_of_duplicated_files_by_size_name > 0
119140
}
120141

121-
fn empty_folders(empty_folders: EmptyFoldersArgs, stop_flag: &Arc<AtomicBool>, progress_sender: &Sender<ProgressData>) {
142+
fn empty_folders(empty_folders: EmptyFoldersArgs, stop_flag: &Arc<AtomicBool>, progress_sender: &Sender<ProgressData>) -> bool {
122143
let EmptyFoldersArgs { common_cli_items, delete_folders } = empty_folders;
123144

124145
let mut item = EmptyFolder::new();
@@ -131,9 +152,11 @@ fn empty_folders(empty_folders: EmptyFoldersArgs, stop_flag: &Arc<AtomicBool>, p
131152
item.find_empty_folders(Some(stop_flag), Some(progress_sender));
132153

133154
save_and_print_results(&item, &common_cli_items);
155+
156+
item.get_information().number_of_empty_folders > 0
134157
}
135158

136-
fn biggest_files(biggest_files: BiggestFilesArgs, stop_flag: &Arc<AtomicBool>, progress_sender: &Sender<ProgressData>) {
159+
fn biggest_files(biggest_files: BiggestFilesArgs, stop_flag: &Arc<AtomicBool>, progress_sender: &Sender<ProgressData>) -> bool {
137160
let BiggestFilesArgs {
138161
common_cli_items,
139162
number_of_files,
@@ -153,9 +176,11 @@ fn biggest_files(biggest_files: BiggestFilesArgs, stop_flag: &Arc<AtomicBool>, p
153176
item.find_big_files(Some(stop_flag), Some(progress_sender));
154177

155178
save_and_print_results(&item, &common_cli_items);
179+
180+
item.get_information().number_of_real_files > 0
156181
}
157182

158-
fn empty_files(empty_files: EmptyFilesArgs, stop_flag: &Arc<AtomicBool>, progress_sender: &Sender<ProgressData>) {
183+
fn empty_files(empty_files: EmptyFilesArgs, stop_flag: &Arc<AtomicBool>, progress_sender: &Sender<ProgressData>) -> bool {
159184
let EmptyFilesArgs { common_cli_items, delete_files } = empty_files;
160185

161186
let mut item = EmptyFiles::new();
@@ -168,9 +193,11 @@ fn empty_files(empty_files: EmptyFilesArgs, stop_flag: &Arc<AtomicBool>, progres
168193
item.find_empty_files(Some(stop_flag), Some(progress_sender));
169194

170195
save_and_print_results(&item, &common_cli_items);
196+
197+
item.get_information().number_of_empty_files > 0
171198
}
172199

173-
fn temporary(temporary: TemporaryArgs, stop_flag: &Arc<AtomicBool>, progress_sender: &Sender<ProgressData>) {
200+
fn temporary(temporary: TemporaryArgs, stop_flag: &Arc<AtomicBool>, progress_sender: &Sender<ProgressData>) -> bool {
174201
let TemporaryArgs { common_cli_items, delete_files } = temporary;
175202

176203
let mut item = Temporary::new();
@@ -183,9 +210,11 @@ fn temporary(temporary: TemporaryArgs, stop_flag: &Arc<AtomicBool>, progress_sen
183210
item.find_temporary_files(Some(stop_flag), Some(progress_sender));
184211

185212
save_and_print_results(&item, &common_cli_items);
213+
214+
item.get_information().number_of_temporary_files > 0
186215
}
187216

188-
fn similar_images(similar_images: SimilarImagesArgs, stop_flag: &Arc<AtomicBool>, progress_sender: &Sender<ProgressData>) {
217+
fn similar_images(similar_images: SimilarImagesArgs, stop_flag: &Arc<AtomicBool>, progress_sender: &Sender<ProgressData>) -> bool {
189218
let SimilarImagesArgs {
190219
common_cli_items,
191220
reference_directories,
@@ -221,9 +250,11 @@ fn similar_images(similar_images: SimilarImagesArgs, stop_flag: &Arc<AtomicBool>
221250
item.find_similar_images(Some(stop_flag), Some(progress_sender));
222251

223252
save_and_print_results(&item, &common_cli_items);
253+
254+
item.get_information().number_of_duplicates > 0
224255
}
225256

226-
fn same_music(same_music: SameMusicArgs, stop_flag: &Arc<AtomicBool>, progress_sender: &Sender<ProgressData>) {
257+
fn same_music(same_music: SameMusicArgs, stop_flag: &Arc<AtomicBool>, progress_sender: &Sender<ProgressData>) -> bool {
227258
let SameMusicArgs {
228259
common_cli_items,
229260
reference_directories,
@@ -258,9 +289,11 @@ fn same_music(same_music: SameMusicArgs, stop_flag: &Arc<AtomicBool>, progress_s
258289
item.find_same_music(Some(stop_flag), Some(progress_sender));
259290

260291
save_and_print_results(&item, &common_cli_items);
292+
293+
item.get_information().number_of_duplicates > 0
261294
}
262295

263-
fn invalid_symlinks(invalid_symlinks: InvalidSymlinksArgs, stop_flag: &Arc<AtomicBool>, progress_sender: &Sender<ProgressData>) {
296+
fn invalid_symlinks(invalid_symlinks: InvalidSymlinksArgs, stop_flag: &Arc<AtomicBool>, progress_sender: &Sender<ProgressData>) -> bool {
264297
let InvalidSymlinksArgs { common_cli_items, delete_files } = invalid_symlinks;
265298

266299
let mut item = InvalidSymlinks::new();
@@ -273,9 +306,11 @@ fn invalid_symlinks(invalid_symlinks: InvalidSymlinksArgs, stop_flag: &Arc<Atomi
273306
item.find_invalid_links(Some(stop_flag), Some(progress_sender));
274307

275308
save_and_print_results(&item, &common_cli_items);
309+
310+
item.get_information().number_of_invalid_symlinks > 0
276311
}
277312

278-
fn broken_files(broken_files: BrokenFilesArgs, stop_flag: &Arc<AtomicBool>, progress_sender: &Sender<ProgressData>) {
313+
fn broken_files(broken_files: BrokenFilesArgs, stop_flag: &Arc<AtomicBool>, progress_sender: &Sender<ProgressData>) -> bool {
279314
let BrokenFilesArgs {
280315
common_cli_items,
281316
delete_files,
@@ -297,9 +332,11 @@ fn broken_files(broken_files: BrokenFilesArgs, stop_flag: &Arc<AtomicBool>, prog
297332
item.find_broken_files(Some(stop_flag), Some(progress_sender));
298333

299334
save_and_print_results(&item, &common_cli_items);
335+
336+
item.get_information().number_of_broken_files > 0
300337
}
301338

302-
fn similar_videos(similar_videos: SimilarVideosArgs, stop_flag: &Arc<AtomicBool>, progress_sender: &Sender<ProgressData>) {
339+
fn similar_videos(similar_videos: SimilarVideosArgs, stop_flag: &Arc<AtomicBool>, progress_sender: &Sender<ProgressData>) -> bool {
303340
let SimilarVideosArgs {
304341
reference_directories,
305342
common_cli_items,
@@ -324,9 +361,11 @@ fn similar_videos(similar_videos: SimilarVideosArgs, stop_flag: &Arc<AtomicBool>
324361
item.find_similar_videos(Some(stop_flag), Some(progress_sender));
325362

326363
save_and_print_results(&item, &common_cli_items);
364+
365+
item.get_information().number_of_duplicates > 0
327366
}
328367

329-
fn bad_extensions(bad_extensions: BadExtensionsArgs, stop_flag: &Arc<AtomicBool>, progress_sender: &Sender<ProgressData>) {
368+
fn bad_extensions(bad_extensions: BadExtensionsArgs, stop_flag: &Arc<AtomicBool>, progress_sender: &Sender<ProgressData>) -> bool {
330369
let BadExtensionsArgs { common_cli_items } = bad_extensions;
331370

332371
let params = BadExtensionsParameters::new();
@@ -337,6 +376,8 @@ fn bad_extensions(bad_extensions: BadExtensionsArgs, stop_flag: &Arc<AtomicBool>
337376
item.find_bad_extensions_files(Some(stop_flag), Some(progress_sender));
338377

339378
save_and_print_results(&item, &common_cli_items);
379+
380+
item.get_information().number_of_files_with_bad_extension > 0
340381
}
341382

342383
fn save_and_print_results<T: CommonData + PrintResults>(component: &T, common_cli_items: &CommonCliItems) {
@@ -356,9 +397,13 @@ fn save_and_print_results<T: CommonData + PrintResults>(component: &T, common_cl
356397
}
357398
}
358399

359-
component.print_results_to_output();
400+
if !common_cli_items.do_not_print.do_not_print_results {
401+
component.print_results_to_output();
402+
}
360403

361-
component.get_text_messages().print_messages();
404+
if !common_cli_items.do_not_print.do_not_print_messages {
405+
component.get_text_messages().print_messages();
406+
}
362407
}
363408

364409
fn set_common_settings<T>(component: &mut T, common_cli_items: &CommonCliItems, reference_directories: Option<&Vec<PathBuf>>)

czkawka_cli/src/progress.rs

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use std::time::Duration;
33
use crossbeam_channel::Receiver;
44
use czkawka_core::common_dir_traversal::ToolType;
55
use czkawka_core::progress_data::{CurrentStage, ProgressData};
6+
use humansize::{BINARY, format_size};
67
use indicatif::{ProgressBar, ProgressStyle};
78

89
pub fn connect_progress(progress_receiver: &Receiver<ProgressData>) {
@@ -16,17 +17,38 @@ pub fn connect_progress(progress_receiver: &Receiver<ProgressData>) {
1617
pb = get_progress_bar_for_collect_files();
1718
} else if progress_data.sstage.check_if_loading_saving_cache() {
1819
pb = get_progress_loading_saving_cache(progress_data.sstage.check_if_loading_cache());
20+
} else if progress_data.bytes_to_check != 0 {
21+
pb = get_progress_known_values(progress_data.bytes_to_check);
1922
} else {
20-
pb = get_progress_known_values(progress_data.entries_to_check, &get_progress_message(&progress_data));
23+
pb = get_progress_known_values(progress_data.entries_to_check as u64);
2124
}
2225
latest_id = Some(progress_data.current_stage_idx);
2326
}
2427

25-
pb.set_position(progress_data.entries_checked as u64);
2628
if progress_data.sstage == CurrentStage::CollectingFiles && progress_data.tool_type != ToolType::EmptyFolders {
2729
pb.set_message(format!("Collecting files: {}", progress_data.entries_checked));
2830
} else if progress_data.sstage == CurrentStage::CollectingFiles {
2931
pb.set_message(format!("Collecting folders: {}", progress_data.entries_checked));
32+
} else if !progress_data.sstage.check_if_loading_saving_cache() {
33+
if progress_data.bytes_to_check != 0 {
34+
pb.set_position(progress_data.bytes_checked);
35+
pb.set_message(format!(
36+
"{}: {}/{} ({}/{})",
37+
get_progress_message(&progress_data),
38+
progress_data.entries_checked,
39+
progress_data.entries_to_check,
40+
format_size(progress_data.bytes_checked, BINARY),
41+
format_size(progress_data.bytes_to_check, BINARY)
42+
));
43+
} else {
44+
pb.set_position(progress_data.entries_checked as u64);
45+
pb.set_message(format!(
46+
"{}: {}/{}",
47+
get_progress_message(&progress_data),
48+
progress_data.entries_checked,
49+
progress_data.entries_to_check
50+
));
51+
}
3052
}
3153
}
3254
pb.finish();
@@ -45,7 +67,7 @@ pub fn get_progress_message(progress_data: &ProgressData) -> String {
4567
CurrentStage::SimilarVideosCalculatingHashes => "Reading similar values",
4668
CurrentStage::BrokenFilesChecking => "Checking broken files",
4769
CurrentStage::BadExtensionsChecking => "Checking extensions of files",
48-
_ => unreachable!(),
70+
_ => panic!("Unknown stage {:?}", progress_data.sstage),
4971
}
5072
.to_string()
5173
}
@@ -54,18 +76,17 @@ pub fn get_progress_bar_for_collect_files() -> ProgressBar {
5476
let pb = ProgressBar::new_spinner();
5577
pb.enable_steady_tick(Duration::from_millis(120));
5678
pb.set_style(
57-
// #[allow(clippy::literal_string_with_formatting_args)] // TODO - enable after being backported to stable
5879
ProgressStyle::with_template("{msg} {spinner:.blue}")
5980
.expect("Failed to create progress bar style")
6081
.tick_strings(&["▹▹▹▹▹", "▸▹▹▹▹", "▹▸▹▹▹", "▹▹▸▹▹", "▹▹▹▸▹", "▹▹▹▹▸", "▪▪▪▪▪"]),
6182
);
6283
pb
6384
}
6485

65-
pub fn get_progress_known_values(max_value: usize, msg: &str) -> ProgressBar {
66-
let pb = ProgressBar::new(max_value as u64);
86+
pub fn get_progress_known_values(max_value: u64) -> ProgressBar {
87+
let pb = ProgressBar::new(max_value);
6788
pb.set_style(
68-
ProgressStyle::with_template(&format!("{msg} [{{bar}}] {{pos}}/{{len}} "))
89+
ProgressStyle::with_template("{msg} [{bar}] ")
6990
.expect("Failed to create progress bar style")
7091
.progress_chars("=> "),
7192
);

0 commit comments

Comments
 (0)