# PhotoSort
PhotoSort is a robust command-line tool written in Rust, designed to streamline the organization of your photo/video
collections. It works by sourcing images/videos from a source directory, extracting the date from either the file name or
its EXIF/metadata data, and then moving or copying the file to a target directory.
PhotoSort solves the problem of having pictures/videos from different cameras and devices that use
different naming conventions to name created files. When viewing the photos/videos in a file browser
this can be confusing, as the photos/videos are not sorted by date. PhotoSort solves this problem by
renaming images/videos based on their EXIF/metadata data or file name, unifying the naming convention and making
to go through the photos/videos by date.
The documentation can be found here: https://docs.rs/photo_sort
## Features
- **Custom Target Format**: You can define your own target date and file name formats for the renamed files.
- **Analysis Mode**: Choose how you want to extract the date from your files. Only EXIF, only name, or a combination.
- **Move Mode**: Choose how you want to move the files to the target directory. Options are moving, coping, hardlinking,
symlinking, or relative symlinking.
- **Recursive Source Directory**: PhotoSort can search the source directories recursively.
- **Dry Run Mode**: Test the tool without making any changes to your files. The tool will print the actions it would
take without actually executing them.
- **Sort photos and videos**: PhotoSort can sort both photos and videos by their metadata.
## Usage
To use PhotoSort, you need to pass in a set of arguments to define how you want to sort your photos. Here is an example:
```bash
photo_sort \
--source-dir /path/to/photos \
--target-dir /path/to/sorted_photos
```
This command will sort the photos in the `/path/to/photos` directory, rename them based on their EXIF data or name and
then move
them to the `/path/to/sorted_photos` directory.
> You are not sure what the tool will do? Run it with the `--dry-run` flag to see what it would do without actually
> changing anything.
Another example:
```bash
photo_sort \
--source_dir /path/to/photos \
--recursive \
--target-dir /path/to/sorted_photos \
--analysis-mode "exif_then_name" \
--date-format "%Y-%m-%d-_%H%M%S" \
--file-format "{date?%Y}/{date}{_:dup}.{ext}" \
--mkdir \
--extensions "png,jpg" \
--move-mode "hardlink"
```
This command will sort the photos in the `/path/to/photos` directory and its subdirectories, rename them based on their
EXIF date (if not found then its name) and then hardlink them to the `/path/to/sorted_photos` directory.
The files will be renamed to the format `YYYY-MM-DD_HHMMSS[_##]`, only `.png` and `.jpg` files will be processed.
The files will be placed in subdirectories based on the year part of the extracted date. Subdirectories will be automatically
created.
For a full list of available options, run `photo_sort --help`:
```text
$ photo_sort --help
A tool to rename and sort photos/videos by its EXIF date/metadata. It tries to extract the date
from the EXIF data or file name and renames the image file according to a given
format string.
Usage: photo_sort [OPTIONS] --source-dir <SOURCE_DIR>... --target-dir <TARGET_DIR>
Options:
-s, --source-dir <SOURCE_DIR>... The source directory to read the photos from
-t, --target-dir <TARGET_DIR> The target directory to write the sorted photos to
-r, --recursive Whether to search the source directories recursively. If the flag is not set only
immediate children of the source directories are considered
--date-format <DATE_FORMAT> Date format string to use as default date format. See [https://docs.rs/chrono/latest/chrono/format/strftime/index.html]
for more information [default: %Y%m%d-%H%M%S]
-f, --file-format <FILE_FORMAT> The target file format. Everything outside a {...} block is copied as is. The
target file format may contain "/" to indicate that the file should be placed in
a subdirectory. Use the `--mkdir` flag to create the subdirectories. `{name}` is
replaced with a filename without the date part. `{dup}` is replaced with a number
if a file with the target name already exists. `{date}` is replaced with the date
string, formatted according to the date_format parameter. `{date?format}` is
replaced with the date string, formatted according to the "format" parameter.
See [https://docs.rs/chrono/latest/chrono/format/strftime/index.html] for more
information. `{type}` is replaced with MOV or IMG. `{type?img,vid}` is replaced
with `img` if the file is an image, `vid` if the file is a video. Note that, when
using other types than IMG or MOV, and rerunning the program again, the custom
type will be seen as part of the file name. `{ext?upper/lower/copy}` is replaced
with the original file extension. If `?upper` or `?lower` is specified, the
extension will be made lower/upper case. leaving out `?...` or using `copy` copies
the original file extension. Commands of the form {label:cmd} are
replaced by {cmd}; if the replacement string is not empty then a prefix of "label"
is added. This might be useful to add separators only if there is e.g. a {dup}
part [default: {type}{_:date}{-:name}{-:dup}]
--mkdir If the file format contains a "/", indicating that the file should be placed in a
subdirectory, the mkdir flag controls if the tool is allowed to create non-existing subdirectories. No folder is
created in dry-run mode
-e, --extensions [<EXTENSIONS>...] A comma separated list of file extensions to include in the analysis
[default: jpg,jpeg,png,tiff,heif,heic,avif,webp]
-a, --analysis-mode <ANALYSIS_MODE> The sorting mode, possible values are name_then_exif, exif_then_name, only_name,
only_exif. Name analysis tries to extract the date from the file name, Exif
analysis tries to extract the date from the EXIF data [default: exif_then_name]
-m, --move-mode <MOVE_MODE> The action mode, possible values are move, copy, hardlink, relative_symlink,
absolute_symlink. Move will move the files, Copy will copy the files, Hardlink
(alias: hard) will create hardlinks, RelativeSymlink (alias: relsym) will create
relative symlinks, AbsoluteSymlink (alias: abssym) will create absolute symlinks
[default: move]
-n, --dry-run Dry-run If set, the tool will not move any files but only print the actions it would take
-v, --verbose Be verbose, if set, the tool will print more information about the actions it takes.
Setting the RUST_LOG env var overrides this flag
-d, --debug Debug, if set, the tool will print debug information (including debug implies
setting verbose). Setting the RUST_LOG env var overrides this flag
-h, --help Print help
-V, --version Print version
When building with video support enabled (see below):
--video-extensions [<VIDEO_EXTENSIONS>...] A comma separated list of video extensions to include in the analysis [default: mp4,mov,avi]
```
## Installation
To install PhotoSort, you need to have Cargo installed on your system.
```bash
cargo install photo_sort
```
or
```bash
git clone https://github.com/0xCCF4/photo_sort.git
cd photo_sort
cargo install --path .
```
The `photo_sort` binary will then be available.
For using the video sorting feature follow the instructions on <https://crates.io/crates/ffmpeg-next> and respective
their wiki <https://github.com/zmwangx/rust-ffmpeg/wiki/Notes-on-building>. After installing the
dependencies, you can install the `photo_sort` binary with the `video` feature enabled:
```bash
cargo install --features video photo_sort
```
or
```bash
git clone https://github.com/0xCCF4/photo_sort.git
cd photo_sort
cargo install --features video --path .
```
## Contributing
Contributions to PhotoSort are welcome! If you have a feature request, bug report, or want to contribute to the code,
please open an issue or a pull request.
### Something works differently than expected?
Try running the tool with the `RUST_LOG` environment variable set to `trace` to get more information about what the tool
is doing and open an issue with the output.
```bash
RUST_LOG=trace photo_sort --source_dir /path/to/photos --target_dir /path/to/sorted_photos
```
## License
PhotoSort is licensed under the GPLv3 license. See the LICENSE file for more details.