2021-11-28 08:49:20 +13:00
use std ::path ::PathBuf ;
2022-04-03 02:11:28 +12:00
use image_hasher ::{ FilterType , HashAlg } ;
2021-11-28 08:49:20 +13:00
2022-01-02 09:07:20 +13:00
use czkawka_core ::common_dir_traversal ::CheckingMethod ;
2023-10-11 07:54:41 +13:00
use czkawka_core ::common_tool ::DeleteMethod ;
use czkawka_core ::duplicate ::HashType ;
2020-11-03 09:56:07 +13:00
use czkawka_core ::same_music ::MusicSimilarity ;
2021-11-18 23:23:17 +13:00
use czkawka_core ::similar_images ::SimilarityPreset ;
2022-08-18 02:58:16 +12:00
use czkawka_core ::CZKAWKA_VERSION ;
2020-11-03 09:56:07 +13:00
2022-12-20 22:19:30 +13:00
#[ derive(clap::Parser) ]
#[ clap(
name = " czkawka " ,
help_template = HELP_TEMPLATE ,
version = CZKAWKA_VERSION
) ]
pub struct Args {
#[ command(subcommand) ]
pub command : Commands ,
}
#[ derive(Debug, clap::Subcommand) ]
2020-10-05 10:36:49 +13:00
pub enum Commands {
2022-12-20 22:19:30 +13:00
#[ clap(
name = " dup " ,
about = " Finds duplicate files " ,
after_help = " EXAMPLE: \n czkawka dup -d /home/rafal -e /home/rafal/Obrazy -m 25 -x 7z rar IMAGE -s hash -f results.txt -D aeo "
) ]
Duplicates ( DuplicatesArgs ) ,
#[ clap(
name = " empty-folders " ,
about = " Finds empty folders " ,
after_help = " EXAMPLE: \n czkawka empty-folders -d /home/rafal/rr /home/gateway -f results.txt "
) ]
EmptyFolders ( EmptyFoldersArgs ) ,
#[ clap(
name = " big " ,
about = " Finds big files " ,
after_help = " EXAMPLE: \n czkawka big -d /home/rafal/ /home/piszczal -e /home/rafal/Roman -n 25 -J -x VIDEO -f results.txt "
) ]
BiggestFiles ( BiggestFilesArgs ) ,
#[ clap(
name = " empty-files " ,
about = " Finds empty files " ,
after_help = " EXAMPLE: \n czkawka empty-files -d /home/rafal /home/szczekacz -e /home/rafal/Pulpit -R -f results.txt "
) ]
EmptyFiles ( EmptyFilesArgs ) ,
#[ clap(
name = " temp " ,
about = " Finds temporary files " ,
after_help = " EXAMPLE: \n czkawka temp -d /home/rafal/ -E */.git */tmp* *Pulpit -f results.txt -D "
) ]
Temporary ( TemporaryArgs ) ,
#[ clap(
name = " image " ,
about = " Finds similar images " ,
after_help = " EXAMPLE: \n czkawka image -d /home/rafal/ -E */.git */tmp* *Pulpit -f results.txt "
) ]
SimilarImages ( SimilarImagesArgs ) ,
#[ clap(name = " music " , about = " Finds same music by tags " , after_help = " EXAMPLE: \n czkawka music -d /home/rafal -f results.txt " ) ]
SameMusic ( SameMusicArgs ) ,
#[ clap(
name = " symlinks " ,
about = " Finds invalid symlinks " ,
after_help = " EXAMPLE: \n czkawka symlinks -d /home/kicikici/ /home/szczek -e /home/kicikici/jestempsem -x jpg -f results.txt "
) ]
InvalidSymlinks ( InvalidSymlinksArgs ) ,
#[ clap(
name = " broken " ,
about = " Finds broken files " ,
after_help = " EXAMPLE: \n czkawka broken -d /home/kicikici/ /home/szczek -e /home/kicikici/jestempsem -x jpg -f results.txt "
) ]
BrokenFiles ( BrokenFilesArgs ) ,
#[ clap(name = " video " , about = " Finds similar video files " , after_help = " EXAMPLE: \n czkawka videos -d /home/rafal -f results.txt " ) ]
SimilarVideos ( SimilarVideosArgs ) ,
#[ clap(
name = " ext " ,
about = " Finds files with invalid extensions " ,
after_help = " EXAMPLE: \n czkawka broken -d /home/czokolada/ -f results.txt "
) ]
BadExtensions ( BadExtensionsArgs ) ,
#[ clap(name = " tester " , about = " Small utility to test supported speed of " , after_help = " EXAMPLE: \n czkawka tester " ) ]
Tester ,
}
#[ derive(Debug, clap::Args) ]
pub struct DuplicatesArgs {
2023-05-11 07:27:41 +12:00
#[ clap(flatten) ]
2024-01-15 02:38:55 +13:00
pub common_cli_items : CommonCliItems ,
2022-12-20 22:19:30 +13:00
#[ clap(
short ,
long ,
value_parser = parse_minimal_file_size ,
default_value = " 8192 " ,
help = " Minimum size in bytes " ,
2024-03-22 11:14:35 +13:00
long_help = " Minimum size of checked files in bytes; assigning bigger values may speed up searching "
2022-12-20 22:19:30 +13:00
) ]
pub minimal_file_size : u64 ,
#[ clap(
short = 'i' ,
long ,
value_parser = parse_maximal_file_size ,
default_value = " 18446744073709551615 " ,
help = " Maximum size in bytes " ,
2024-03-22 11:14:35 +13:00
long_help = " Maximum size of checked files in bytes; assigning lower values may speed up searching "
2022-12-20 22:19:30 +13:00
) ]
pub maximal_file_size : u64 ,
#[ clap(
short = 'c' ,
long ,
value_parser = parse_minimal_file_size ,
default_value = " 257144 " ,
help = " Minimum cached file size in bytes " ,
2024-03-22 11:14:35 +13:00
long_help = " Minimum size of cached files in bytes; assigning bigger values may speed up the scan, but loading the cache will be slower; assigning smaller values may slow down the scan and some files may need to be hashed again, but loading the cache will be faster "
2022-12-20 22:19:30 +13:00
) ]
pub minimal_cached_file_size : u64 ,
#[ clap(
short ,
long ,
default_value = " HASH " ,
2023-10-14 07:33:17 +13:00
value_parser = parse_checking_method_duplicate ,
2022-12-20 22:19:30 +13:00
help = " Search method (NAME, SIZE, HASH) " ,
2024-03-22 11:14:35 +13:00
long_help = " Methods to search files: \n NAME - Fast but but rarely usable; \n SIZE - Fast but not accurate, checking by the file's size; \n HASH - The slowest method, checking by the hash of the entire file. "
2022-12-20 22:19:30 +13:00
) ]
pub search_method : CheckingMethod ,
2023-10-14 07:33:17 +13:00
#[ clap(flatten) ]
pub delete_method : DMethod ,
2022-12-20 22:19:30 +13:00
#[ clap(
short = 't' ,
long ,
default_value = " BLAKE3 " ,
value_parser = parse_hash_type ,
help = " Hash type (BLAKE3, CRC32, XXH3) "
) ]
pub hash_type : HashType ,
#[ clap(flatten) ]
pub case_sensitive_name_comparison : CaseSensitiveNameComparison ,
#[ clap(flatten) ]
pub allow_hard_links : AllowHardLinks ,
#[ clap(flatten) ]
2023-10-14 07:33:17 +13:00
pub dry_run : DryRun ,
2022-12-20 22:19:30 +13:00
}
#[ derive(Debug, clap::Args) ]
pub struct EmptyFoldersArgs {
2023-05-11 07:27:41 +12:00
#[ clap(flatten) ]
2024-01-15 02:38:55 +13:00
pub common_cli_items : CommonCliItems ,
2022-12-20 22:19:30 +13:00
#[ clap(short = 'D', long, help = " Delete found folders " ) ]
pub delete_folders : bool ,
}
#[ derive(Debug, clap::Args) ]
pub struct BiggestFilesArgs {
2023-05-11 07:27:41 +12:00
#[ clap(flatten) ]
2024-01-15 02:38:55 +13:00
pub common_cli_items : CommonCliItems ,
2022-12-20 22:19:30 +13:00
#[ clap(short, long, default_value = " 50 " , help = " Number of files to be shown " ) ]
pub number_of_files : usize ,
#[ clap(short = 'D', long, help = " Delete found files " ) ]
pub delete_files : bool ,
#[ clap(short = 'J', long, help = " Finds the smallest files instead the biggest " ) ]
pub smallest_mode : bool ,
}
#[ derive(Debug, clap::Args) ]
pub struct EmptyFilesArgs {
2023-05-11 07:27:41 +12:00
#[ clap(flatten) ]
2024-01-15 02:38:55 +13:00
pub common_cli_items : CommonCliItems ,
2022-12-20 22:19:30 +13:00
#[ clap(short = 'D', long, help = " Delete found files " ) ]
pub delete_files : bool ,
}
#[ derive(Debug, clap::Args) ]
pub struct TemporaryArgs {
2023-05-11 07:27:41 +12:00
#[ clap(flatten) ]
2024-01-15 02:38:55 +13:00
pub common_cli_items : CommonCliItems ,
2022-12-20 22:19:30 +13:00
#[ clap(short = 'D', long, help = " Delete found files " ) ]
pub delete_files : bool ,
}
#[ derive(Debug, clap::Args) ]
pub struct SimilarImagesArgs {
2023-05-11 07:27:41 +12:00
#[ clap(flatten) ]
2024-01-15 02:38:55 +13:00
pub common_cli_items : CommonCliItems ,
2022-12-20 22:19:30 +13:00
#[ clap(
short ,
long ,
value_parser = parse_minimal_file_size ,
default_value = " 16384 " ,
help = " Minimum size in bytes " ,
2024-03-22 11:14:35 +13:00
long_help = " Minimum size of checked files in bytes; assigning bigger values may speed up searching "
2022-12-20 22:19:30 +13:00
) ]
pub minimal_file_size : u64 ,
#[ clap(
short = 'i' ,
long ,
value_parser = parse_minimal_file_size ,
default_value = " 18446744073709551615 " ,
help = " Maximum size in bytes " ,
2024-03-22 11:14:35 +13:00
long_help = " Maximum size of checked files in bytes; assigning lower values may speed up searching "
2022-12-20 22:19:30 +13:00
) ]
pub maximal_file_size : u64 ,
#[ clap(
short ,
long ,
default_value = " High " ,
value_parser = parse_similar_images_similarity ,
2024-03-22 11:14:35 +13:00
help = " Similarity level (allowed values: Minimal, VerySmall, Small, Medium, High, VeryHigh) " ,
long_help = " Methods to choose similarity level of images which will be considered as duplicated. \n (allowed values: Minimal, VerySmall, Small, Medium, High, VeryHigh) "
2022-12-20 22:19:30 +13:00
) ]
pub similarity_preset : SimilarityPreset ,
#[ clap(flatten) ]
2023-10-14 07:33:17 +13:00
pub delete_method : DMethod ,
#[ clap(flatten) ]
2024-02-15 05:41:17 +13:00
pub allow_hard_links : AllowHardLinks ,
#[ clap(flatten) ]
2023-10-14 07:33:17 +13:00
pub dry_run : DryRun ,
2022-12-20 22:19:30 +13:00
#[ clap(
short = 'g' ,
long ,
default_value = " Gradient " ,
value_parser = parse_similar_hash_algorithm ,
2024-03-22 11:14:35 +13:00
help = " Hash algorithm (allowed values: Mean, Gradient, Blockhash, VertGradient, DoubleGradient) "
2022-12-20 22:19:30 +13:00
) ]
pub hash_alg : HashAlg ,
#[ clap(
short = 'z' ,
long ,
default_value = " Nearest " ,
value_parser = parse_similar_image_filter ,
2024-03-22 11:14:35 +13:00
help = " Hash algorithm (allowed values: Lanczos3, Nearest, Triangle, Faussian, Catmullrom) "
2022-12-20 22:19:30 +13:00
) ]
pub image_filter : FilterType ,
#[ clap(
short = 'c' ,
long ,
default_value = " 16 " ,
value_parser = parse_image_hash_size ,
2024-03-22 11:14:35 +13:00
help = " Hash size (allowed values: 8, 16, 32, 64) "
2022-12-20 22:19:30 +13:00
) ]
pub hash_size : u8 ,
}
#[ derive(Debug, clap::Args) ]
pub struct SameMusicArgs {
2023-05-11 07:27:41 +12:00
#[ clap(flatten) ]
2024-01-15 02:38:55 +13:00
pub common_cli_items : CommonCliItems ,
2023-10-14 07:33:17 +13:00
#[ clap(flatten) ]
pub delete_method : DMethod ,
#[ clap(flatten) ]
pub dry_run : DryRun ,
2022-12-20 22:19:30 +13:00
#[ clap(
short = 'z' ,
long ,
default_value = " track_title,track_artist " ,
value_parser = parse_music_duplicate_type ,
help = " Search method (track_title,track_artist,year,bitrate,genre,length)) " ,
2024-03-22 11:14:35 +13:00
long_help = " Sets which rows must be equal to set these files as duplicates (may be mixed, but must be separated by commas). "
2022-12-20 22:19:30 +13:00
) ]
pub music_similarity : MusicSimilarity ,
2023-10-14 07:33:17 +13:00
#[ clap(
short ,
long ,
default_value = " TAGS " ,
value_parser = parse_checking_method_same_music ,
help = " Search method (CONTENT, TAGS) " ,
2024-03-22 11:14:35 +13:00
long_help = " Methods to search files: \n CONTENT - finds similar audio files by content; \n TAGS - finds similar images by tags; needs to set "
2023-10-14 07:33:17 +13:00
) ]
pub search_method : CheckingMethod ,
2022-12-20 22:19:30 +13:00
#[ clap(
short ,
long ,
value_parser = parse_minimal_file_size ,
default_value = " 8192 " ,
help = " Minimum size in bytes " ,
2024-03-22 11:14:35 +13:00
long_help = " Minimum size of checked files in bytes; assigning bigger values may speed up searching "
2022-12-20 22:19:30 +13:00
) ]
pub minimal_file_size : u64 ,
#[ clap(
short = 'i' ,
long ,
value_parser = parse_maximal_file_size ,
default_value = " 18446744073709551615 " ,
help = " Maximum size in bytes " ,
2024-03-22 11:14:35 +13:00
long_help = " Maximum size of checked files in bytes; assigning lower values may speed up searching "
2022-12-20 22:19:30 +13:00
) ]
pub maximal_file_size : u64 ,
2023-10-14 07:33:17 +13:00
#[ clap(
short = 'l' ,
long ,
value_parser = parse_minimum_segment_duration ,
default_value = " 10.0 " ,
help = " Maximum size in bytes " ,
2024-03-22 11:14:35 +13:00
long_help = " Minimum segment duration; smaller values will find also shorter similar segments, which may increase false positives "
2023-10-14 07:33:17 +13:00
) ]
pub minimum_segment_duration : f32 ,
#[ clap(
short = 'd' ,
long ,
value_parser = parse_maximum_difference ,
default_value = " 2.0 " ,
help = " Maximum difference between segments " ,
2024-03-22 11:14:35 +13:00
long_help = " Maximum difference between segments; 0.0 will find only identical segments; 10.0 will find also segments which are almost not similar at all "
2023-10-14 07:33:17 +13:00
) ]
pub maximum_difference : f64 ,
}
fn parse_maximum_difference ( src : & str ) -> Result < f64 , String > {
match src . parse ::< f64 > ( ) {
Ok ( maximum_difference ) = > {
if maximum_difference < = 0.0 {
Err ( " Maximum difference must be bigger than 0 " . to_string ( ) )
} else if maximum_difference > = 10.0 {
Err ( " Maximum difference must be smaller than 10.0 " . to_string ( ) )
} else {
Ok ( maximum_difference )
}
}
Err ( e ) = > Err ( e . to_string ( ) ) ,
}
}
fn parse_minimum_segment_duration ( src : & str ) -> Result < f32 , String > {
match src . parse ::< f32 > ( ) {
Ok ( minimum_segment_duration ) = > {
if minimum_segment_duration < = 0.0 {
Err ( " Minimum segment duration must be bigger than 0 " . to_string ( ) )
} else if minimum_segment_duration > = 3600.0 {
2024-03-22 11:14:35 +13:00
Err ( " Minimum segment duration must be smaller than 3600 (greater values not make much sense) " . to_string ( ) )
2023-10-14 07:33:17 +13:00
} else {
Ok ( minimum_segment_duration )
}
}
Err ( e ) = > Err ( e . to_string ( ) ) ,
}
2022-12-20 22:19:30 +13:00
}
#[ derive(Debug, clap::Args) ]
pub struct InvalidSymlinksArgs {
2023-05-11 07:27:41 +12:00
#[ clap(flatten) ]
2024-01-15 02:38:55 +13:00
pub common_cli_items : CommonCliItems ,
2022-12-20 22:19:30 +13:00
#[ clap(short = 'D', long, help = " Delete found files " ) ]
pub delete_files : bool ,
}
#[ derive(Debug, clap::Args) ]
pub struct BrokenFilesArgs {
2023-05-11 07:27:41 +12:00
#[ clap(flatten) ]
2024-01-15 02:38:55 +13:00
pub common_cli_items : CommonCliItems ,
2022-12-20 22:19:30 +13:00
#[ clap(short = 'D', long, help = " Delete found files " ) ]
pub delete_files : bool ,
}
#[ derive(Debug, clap::Args) ]
pub struct SimilarVideosArgs {
2023-05-11 07:27:41 +12:00
#[ clap(flatten) ]
2024-01-15 02:38:55 +13:00
pub common_cli_items : CommonCliItems ,
2023-10-14 07:33:17 +13:00
#[ clap(flatten) ]
pub delete_method : DMethod ,
#[ clap(flatten) ]
2024-02-15 05:41:17 +13:00
pub allow_hard_links : AllowHardLinks ,
#[ clap(flatten) ]
2023-10-14 07:33:17 +13:00
pub dry_run : DryRun ,
2022-12-20 22:19:30 +13:00
#[ clap(
short ,
long ,
value_parser = parse_minimal_file_size ,
default_value = " 8192 " ,
help = " Minimum size in bytes " ,
2024-03-22 11:14:35 +13:00
long_help = " Minimum size of checked files in bytes; assigning bigger values may speed up searching "
2022-12-20 22:19:30 +13:00
) ]
pub minimal_file_size : u64 ,
#[ clap(
short = 'i' ,
long ,
value_parser = parse_maximal_file_size ,
default_value = " 18446744073709551615 " ,
help = " Maximum size in bytes " ,
2024-03-22 11:14:35 +13:00
long_help = " Maximum size of checked files in bytes; assigning lower values may speed up searching "
2022-12-20 22:19:30 +13:00
) ]
pub maximal_file_size : u64 ,
#[ clap(
short = 't' ,
long ,
value_parser = parse_tolerance ,
default_value = " 10 " ,
2024-03-22 11:14:35 +13:00
help = " Video maximum difference (allowed values: <0,20>) " ,
long_help = " Maximum difference between video frames; bigger values mean that videos can look more and more different (allowed values: <0,20>) "
2022-12-20 22:19:30 +13:00
) ]
pub tolerance : i32 ,
}
#[ derive(Debug, clap::Args) ]
pub struct BadExtensionsArgs {
2023-05-11 07:27:41 +12:00
#[ clap(flatten) ]
2024-01-15 02:38:55 +13:00
pub common_cli_items : CommonCliItems ,
2022-12-20 22:19:30 +13:00
}
2023-10-14 07:33:17 +13:00
#[ derive(Debug, clap::Args) ]
2024-01-15 02:38:55 +13:00
pub struct CommonCliItems {
2024-03-22 11:14:35 +13:00
#[ clap(short = 'T', long, default_value = " 0 " , help = " Limits number of threads; 0 (default) will use all available threads " ) ]
2024-01-15 02:38:55 +13:00
pub thread_number : usize ,
2022-06-18 20:59:46 +12:00
#[ clap(
2021-12-22 06:44:20 +13:00
short ,
long ,
required = true ,
2024-03-22 11:14:35 +13:00
help = " Directory(ies) to search " ,
long_help = " List of directories which will be searched (absolute path) "
2021-12-22 06:44:20 +13:00
) ]
2020-10-05 10:36:49 +13:00
pub directories : Vec < PathBuf > ,
2022-06-18 20:59:46 +12:00
#[ clap(
2021-12-22 06:44:20 +13:00
short ,
long ,
2024-03-22 11:14:35 +13:00
help = " Excluded directory(ies) " ,
long_help = " List of directories which will be excluded from search (absolute path) "
2021-12-22 06:44:20 +13:00
) ]
2020-10-05 10:36:49 +13:00
pub excluded_directories : Vec < PathBuf > ,
2022-06-18 20:59:46 +12:00
#[ clap(
short = 'E' ,
2021-12-22 06:44:20 +13:00
long ,
help = " Excluded item(s) " ,
2024-03-22 11:14:35 +13:00
long_help = " List of excluded item(s) which contains * wildcard (may be slow, so use -e where possible) "
2021-12-22 06:44:20 +13:00
) ]
2021-01-11 08:44:10 +13:00
pub excluded_items : Vec < String > ,
2022-06-18 20:59:46 +12:00
#[ clap(
short = 'x' ,
2020-10-05 10:36:49 +13:00
long ,
help = " Allowed file extension(s) " ,
2021-01-14 04:03:05 +13:00
long_help = " List of checked files with provided extension(s). There are also helpful macros which allow to easy use a typical extensions like: \n IMAGE( \" jpg,kra,gif,png,bmp,tiff,hdr,svg \" ), \n TEXT( \" txt,doc,docx,odt,rtf \" ), \n VIDEO( \" mp4,flv,mkv,webm,vob,ogv,gifv,avi,mov,wmv,mpg,m4v,m4p,mpeg,3gp \" ) or \n MUSIC( \" mp3,flac,ogg,tta,wma,webm \" ) \n "
2020-10-05 10:36:49 +13:00
) ]
pub allowed_extensions : Vec < String > ,
2024-03-22 11:14:35 +13:00
#[ clap(short = 'P', long, help = " Excluded file extension(s) " , long_help = " List of extensions that will be removed from search. \n " ) ]
2024-02-15 05:45:25 +13:00
pub excluded_extensions : Vec < String > ,
2024-01-15 02:38:55 +13:00
#[ clap(flatten) ]
pub file_to_save : FileToSave ,
#[ clap(flatten) ]
pub json_compact_file_to_save : JsonCompactFileToSave ,
#[ clap(flatten) ]
pub json_pretty_file_to_save : JsonPrettyFileToSave ,
2022-06-18 20:59:46 +12:00
#[ clap(short = 'R', long, help = " Prevents from recursive check of folders " ) ]
2020-10-05 10:36:49 +13:00
pub not_recursive : bool ,
2024-01-15 02:38:55 +13:00
#[ cfg(target_family = " unix " ) ]
#[ clap(short = 'X', long, help = " Exclude files on other filesystems " ) ]
pub exclude_other_filesystems : bool ,
2020-10-05 10:36:49 +13:00
}
2023-05-11 07:27:41 +12:00
#[ derive(Debug, clap::Args) ]
2024-01-15 02:38:55 +13:00
pub struct DMethod {
#[ clap(
short = 'D' ,
long ,
default_value = " NONE " ,
value_parser = parse_delete_method ,
help = " Delete method (AEN, AEO, ON, OO, HARD) " ,
2024-03-22 11:14:35 +13:00
long_help = " Methods to delete the files: \n AEN - All files except the newest; \n AEO - All files except the oldest; \n ON - Only 1 file, the newest; \n OO - Only 1 file, the oldest; \n HARD - create hard link; \n NONE - do not delete files. "
2024-01-15 02:38:55 +13:00
) ]
pub delete_method : DeleteMethod ,
2022-04-24 06:21:46 +12:00
}
2022-12-20 22:19:30 +13:00
#[ derive(Debug, clap::Args) ]
2020-10-05 10:36:49 +13:00
pub struct FileToSave {
2024-03-22 11:14:35 +13:00
#[ clap(short, long, value_name = " file-name " , help = " Saves the results into a formatted txt file " ) ]
2020-10-05 10:36:49 +13:00
pub file_to_save : Option < PathBuf > ,
}
2023-10-13 05:48:46 +13:00
#[ derive(Debug, clap::Args) ]
pub struct JsonCompactFileToSave {
2024-03-22 11:14:35 +13:00
#[ clap(short = 'C', long, value_name = " json-file-name " , help = " Saves the results into a compact json file " ) ]
2023-10-13 05:48:46 +13:00
pub compact_file_to_save : Option < PathBuf > ,
}
#[ derive(Debug, clap::Args) ]
pub struct JsonPrettyFileToSave {
2024-03-22 11:14:35 +13:00
#[ clap(short, long, value_name = " pretty-json-file-name " , help = " Saves the results into a pretty json file " ) ]
2023-10-13 05:48:46 +13:00
pub pretty_file_to_save : Option < PathBuf > ,
}
2022-12-20 22:19:30 +13:00
#[ derive(Debug, clap::Args) ]
2021-02-23 08:14:33 +13:00
pub struct AllowHardLinks {
2022-06-18 20:59:46 +12:00
#[ clap(short = 'L', long, help = " Do not ignore hard links " ) ]
2021-02-23 08:14:33 +13:00
pub allow_hard_links : bool ,
}
2022-12-20 22:19:30 +13:00
#[ derive(Debug, clap::Args) ]
2022-07-31 18:45:19 +12:00
pub struct CaseSensitiveNameComparison {
#[ clap(short = 'l', long, help = " Use case sensitive name comparison " ) ]
pub case_sensitive_name_comparison : bool ,
}
2022-12-20 22:19:30 +13:00
#[ derive(Debug, clap::Args) ]
2021-03-02 00:23:43 +13:00
pub struct DryRun {
2022-06-18 20:59:46 +12:00
#[ clap(long, help = " Do nothing and print the operation that would happen. " ) ]
2023-10-14 07:33:17 +13:00
pub dry_run : bool ,
2021-03-02 00:23:43 +13:00
}
2020-10-05 10:36:49 +13:00
impl FileToSave {
pub fn file_name ( & self ) -> Option < & str > {
if let Some ( file_name ) = & self . file_to_save {
return file_name . to_str ( ) ;
}
None
}
}
2023-10-13 05:48:46 +13:00
impl JsonCompactFileToSave {
pub fn file_name ( & self ) -> Option < & str > {
if let Some ( file_name ) = & self . compact_file_to_save {
return file_name . to_str ( ) ;
}
None
}
}
impl JsonPrettyFileToSave {
pub fn file_name ( & self ) -> Option < & str > {
if let Some ( file_name ) = & self . pretty_file_to_save {
return file_name . to_str ( ) ;
}
None
}
}
2020-10-05 10:36:49 +13:00
2021-02-21 17:59:07 +13:00
fn parse_hash_type ( src : & str ) -> Result < HashType , & 'static str > {
match src . to_ascii_lowercase ( ) . as_str ( ) {
" blake3 " = > Ok ( HashType ::Blake3 ) ,
2021-03-28 01:14:02 +13:00
" crc32 " = > Ok ( HashType ::Crc32 ) ,
" xxh3 " = > Ok ( HashType ::Xxh3 ) ,
2024-03-22 11:14:35 +13:00
_ = > Err ( " Couldn't parse the hash type (allowed values: BLAKE3, CRC32, XXH3) " ) ,
2021-02-21 17:59:07 +13:00
}
}
2021-11-23 23:10:24 +13:00
fn parse_tolerance ( src : & str ) -> Result < i32 , & 'static str > {
match src . parse ::< i32 > ( ) {
Ok ( t ) = > {
if ( 0 ..= 20 ) . contains ( & t ) {
Ok ( t )
} else {
2024-03-22 11:14:35 +13:00
Err ( " Tolerance should be in range <0,20> (higher and lower similarity) " )
2021-11-23 23:10:24 +13:00
}
}
_ = > Err ( " Failed to parse tolerance as i32 value. " ) ,
}
}
2023-10-14 07:33:17 +13:00
fn parse_checking_method_duplicate ( src : & str ) -> Result < CheckingMethod , & 'static str > {
2020-10-05 10:36:49 +13:00
match src . to_ascii_lowercase ( ) . as_str ( ) {
2020-10-25 07:44:21 +13:00
" name " = > Ok ( CheckingMethod ::Name ) ,
2020-10-05 10:36:49 +13:00
" size " = > Ok ( CheckingMethod ::Size ) ,
2023-04-05 18:08:43 +12:00
" size_name " = > Ok ( CheckingMethod ::SizeName ) ,
2020-10-05 10:36:49 +13:00
" hash " = > Ok ( CheckingMethod ::Hash ) ,
2024-03-22 11:14:35 +13:00
_ = > Err ( " Couldn't parse the search method (allowed values: NAME, SIZE, HASH) " ) ,
2020-10-05 10:36:49 +13:00
}
}
2023-10-14 07:33:17 +13:00
fn parse_checking_method_same_music ( src : & str ) -> Result < CheckingMethod , & 'static str > {
match src . to_ascii_lowercase ( ) . as_str ( ) {
" tags " = > Ok ( CheckingMethod ::AudioTags ) ,
" content " = > Ok ( CheckingMethod ::AudioContent ) ,
2024-03-22 11:14:35 +13:00
_ = > Err ( " Couldn't parse the searc method (allowed values: TAGS, CONTENT) " ) ,
2023-10-14 07:33:17 +13:00
}
}
2020-10-05 10:36:49 +13:00
fn parse_delete_method ( src : & str ) -> Result < DeleteMethod , & 'static str > {
match src . to_ascii_lowercase ( ) . as_str ( ) {
2020-10-13 02:25:32 +13:00
" none " = > Ok ( DeleteMethod ::None ) ,
2020-10-05 10:36:49 +13:00
" aen " = > Ok ( DeleteMethod ::AllExceptNewest ) ,
" aeo " = > Ok ( DeleteMethod ::AllExceptOldest ) ,
2021-02-06 05:59:34 +13:00
" hard " = > Ok ( DeleteMethod ::HardLink ) ,
2020-10-05 10:36:49 +13:00
" on " = > Ok ( DeleteMethod ::OneNewest ) ,
" oo " = > Ok ( DeleteMethod ::OneOldest ) ,
2024-03-22 11:14:35 +13:00
_ = > Err ( " Couldn't parse the delete method (allowed values: AEN, AEO, ON, OO, HARD) " ) ,
2020-10-05 10:36:49 +13:00
}
}
2021-11-18 23:23:17 +13:00
fn parse_similar_images_similarity ( src : & str ) -> Result < SimilarityPreset , & 'static str > {
match src . to_lowercase ( ) . replace ( '_' , " " ) . as_str ( ) {
" minimal " = > Ok ( SimilarityPreset ::Minimal ) ,
" verysmall " = > Ok ( SimilarityPreset ::VerySmall ) ,
" small " = > Ok ( SimilarityPreset ::Small ) ,
" medium " = > Ok ( SimilarityPreset ::Medium ) ,
" high " = > Ok ( SimilarityPreset ::High ) ,
" veryhigh " = > Ok ( SimilarityPreset ::VeryHigh ) ,
2024-03-22 11:14:35 +13:00
_ = > Err ( " Couldn't parse the image similarity preset (allowed values: Minimal, VerySmall, Small, Medium, High, VeryHigh) " ) ,
2020-11-10 00:55:27 +13:00
}
}
2020-10-07 21:34:15 +13:00
fn parse_minimal_file_size ( src : & str ) -> Result < u64 , String > {
2020-10-05 10:36:49 +13:00
match src . parse ::< u64 > ( ) {
2020-10-15 08:10:27 +13:00
Ok ( minimal_file_size ) = > {
if minimal_file_size > 0 {
Ok ( minimal_file_size )
2020-10-05 10:36:49 +13:00
} else {
Err ( " Minimum file size must be at least 1 byte " . to_string ( ) )
}
}
Err ( e ) = > Err ( e . to_string ( ) ) ,
}
}
2021-08-07 09:23:11 +12:00
fn parse_maximal_file_size ( src : & str ) -> Result < u64 , String > {
match src . parse ::< u64 > ( ) {
Ok ( maximal_file_size ) = > Ok ( maximal_file_size ) ,
Err ( e ) = > Err ( e . to_string ( ) ) ,
}
}
2021-11-18 23:23:17 +13:00
fn parse_similar_image_filter ( src : & str ) -> Result < FilterType , String > {
2021-12-19 11:45:37 +13:00
let filter_type = match src . to_lowercase ( ) . as_str ( ) {
2021-11-18 23:23:17 +13:00
" lanczos3 " = > FilterType ::Lanczos3 ,
" nearest " = > FilterType ::Nearest ,
" triangle " = > FilterType ::Triangle ,
" faussian " = > FilterType ::Gaussian ,
" catmullrom " = > FilterType ::CatmullRom ,
2024-03-22 11:14:35 +13:00
_ = > return Err ( " Couldn't parse the image resize filter (allowed values: Lanczos3, Nearest, Triangle, Faussian, Catmullrom) " . to_string ( ) ) ,
2021-11-18 23:23:17 +13:00
} ;
Ok ( filter_type )
}
2021-11-28 08:57:10 +13:00
2021-11-18 23:23:17 +13:00
fn parse_similar_hash_algorithm ( src : & str ) -> Result < HashAlg , String > {
2021-12-19 11:45:37 +13:00
let algorithm = match src . to_lowercase ( ) . as_str ( ) {
2021-11-18 23:23:17 +13:00
" mean " = > HashAlg ::Mean ,
" gradient " = > HashAlg ::Gradient ,
" blockhash " = > HashAlg ::Blockhash ,
" vertgradient " = > HashAlg ::VertGradient ,
" doublegradient " = > HashAlg ::DoubleGradient ,
2024-03-22 11:14:35 +13:00
_ = > return Err ( " Couldn't parse the hash algorithm (allowed values: Mean, Gradient, Blockhash, VertGradient, DoubleGradient) " . to_string ( ) ) ,
2021-11-18 23:23:17 +13:00
} ;
Ok ( algorithm )
}
fn parse_image_hash_size ( src : & str ) -> Result < u8 , String > {
2021-12-19 11:45:37 +13:00
let hash_size = match src . to_lowercase ( ) . as_str ( ) {
2021-11-18 23:23:17 +13:00
" 8 " = > 8 ,
" 16 " = > 16 ,
2021-12-03 03:33:06 +13:00
" 32 " = > 32 ,
" 64 " = > 64 ,
2024-03-22 11:14:35 +13:00
_ = > return Err ( " Couldn't parse the image hash size (allowed values: 8, 16, 32, 64) " . to_string ( ) ) ,
2021-11-18 23:23:17 +13:00
} ;
Ok ( hash_size )
}
2020-11-03 09:56:07 +13:00
fn parse_music_duplicate_type ( src : & str ) -> Result < MusicSimilarity , String > {
2023-10-14 07:33:17 +13:00
if src . trim ( ) . is_empty ( ) {
2020-11-03 09:56:07 +13:00
return Ok ( MusicSimilarity ::NONE ) ;
}
let mut similarity : MusicSimilarity = MusicSimilarity ::NONE ;
2022-02-26 06:47:25 +13:00
let parts : Vec < String > = src . split ( ',' ) . map ( | e | e . to_lowercase ( ) . replace ( '_' , " " ) ) . collect ( ) ;
2020-11-03 09:56:07 +13:00
2023-10-14 07:33:17 +13:00
if parts . contains ( & " tracktitle " . into ( ) ) {
2022-02-26 06:47:25 +13:00
similarity | = MusicSimilarity ::TRACK_TITLE ;
2020-11-03 09:56:07 +13:00
}
2023-10-14 07:33:17 +13:00
if parts . contains ( & " trackartist " . into ( ) ) {
2022-02-26 06:47:25 +13:00
similarity | = MusicSimilarity ::TRACK_ARTIST ;
2020-11-03 09:56:07 +13:00
}
2023-10-14 07:33:17 +13:00
if parts . contains ( & " year " . into ( ) ) {
2022-02-26 06:47:25 +13:00
similarity | = MusicSimilarity ::YEAR ;
2020-11-03 09:56:07 +13:00
}
2023-10-14 07:33:17 +13:00
if parts . contains ( & " bitrate " . into ( ) ) {
2022-02-26 06:47:25 +13:00
similarity | = MusicSimilarity ::BITRATE ;
2020-11-03 09:56:07 +13:00
}
2023-10-14 07:33:17 +13:00
if parts . contains ( & " genre " . into ( ) ) {
2022-02-26 06:47:25 +13:00
similarity | = MusicSimilarity ::GENRE ;
}
2023-10-14 07:33:17 +13:00
if parts . contains ( & " length " . into ( ) ) {
2022-02-26 06:47:25 +13:00
similarity | = MusicSimilarity ::LENGTH ;
2020-11-03 09:56:07 +13:00
}
if similarity = = MusicSimilarity ::NONE {
2024-03-22 11:14:35 +13:00
return Err ( " Couldn't parse the music search method (allowed values: track_title, track_artist, year, bitrate, genre, length) " . to_string ( ) ) ;
2020-11-03 09:56:07 +13:00
}
Ok ( similarity )
}
2020-10-05 10:36:49 +13:00
const HELP_TEMPLATE : & str = r #"
{ bin } { version }
USAGE :
{ usage } [ SCFLAGS ] [ SCOPTIONS ]
2022-06-18 20:59:46 +12:00
OPTIONS :
{ options }
2020-10-05 10:36:49 +13:00
SUBCOMMANDS :
{ subcommands }
try " {usage} -h " to get more info about a specific tool
EXAMPLES :
2021-12-02 00:37:17 +13:00
{ bin } dup - d / home / rafal - e / home / rafal / Obrazy - m 25 - x 7 z rar IMAGE - s hash - f results . txt - D aeo
2020-10-05 10:36:49 +13:00
{ bin } empty - folders - d / home / rafal / rr / home / gateway - f results . txt
{ bin } big - d / home / rafal / / home / piszczal - e / home / rafal / Roman - n 25 - x VIDEO - f results . txt
{ bin } empty - files - d / home / rafal / home / szczekacz - e / home / rafal / Pulpit - R - f results . txt
2020-10-25 07:44:21 +13:00
{ bin } temp - d / home / rafal / - E * / . git * / tmp * * Pulpit - f results . txt - D
2020-10-31 22:29:11 +13:00
{ bin } image - d / home / rafal - e / home / rafal / Pulpit - f results . txt
2020-12-22 04:09:39 +13:00
{ bin } music - d / home / rafal - e / home / rafal / Pulpit - z " artist,year, ARTISTALBUM, ALBUM___tiTlE " - f results . txt
2021-01-13 08:06:12 +13:00
{ bin } symlinks - d / home / kicikici / / home / szczek - e / home / kicikici / jestempsem - x jpg - f results . txt
2022-11-26 08:38:27 +13:00
{ bin } broken - d / home / mikrut / - e / home / mikrut / trakt - f results . txt
{ bin } extnp - d / home / mikrut / - e / home / mikrut / trakt - f results . txt " #;