diff --git a/browser/files/localassets.go b/browser/files/localassets.go
index 5caf630a..d903a1b0 100644
--- a/browser/files/localassets.go
+++ b/browser/files/localassets.go
@@ -275,6 +275,7 @@ func (la *LocalAssetBrowser) assetFromFile(fsys fs.FS, name string) (*browser.Lo
if fsys, ok := fsys.(fshelper.NameFS); ok {
fullPath = filepath.Join(fsys.Name(), name)
}
+
a.Metadata.DateTaken = metadata.TakeTimeFromPath(fullPath)
i, err := fs.Stat(fsys, name)
diff --git a/cmd/upload/upload.go b/cmd/upload/upload.go
index 8df140e2..f446ca65 100644
--- a/cmd/upload/upload.go
+++ b/cmd/upload/upload.go
@@ -38,6 +38,8 @@ type UpCmd struct {
GooglePhotos bool // For reading Google Photos takeout files
Delete bool // Delete original file after import
CreateAlbumAfterFolder bool // Create albums for assets based on the parent folder or a given name
+ UseFullPathAsAlbumName bool // Create albums for assets based on the full path to the asset
+ AlbumNamePathSeparator string // Determines how multiple (sub) folders, if any, will be joined
ImportIntoAlbum string // All assets will be added to this album
PartnerAlbum string // Partner's assets will be added to this album
Import bool // Import instead of upload
@@ -119,6 +121,14 @@ func newCommand(ctx context.Context, common *cmd.SharedFlags, args []string, fsO
"create-album-folder",
" folder import only: Create albums for assets based on the parent folder",
myflag.BoolFlagFn(&app.CreateAlbumAfterFolder, false))
+ cmd.BoolFunc(
+ "use-full-path-album-name",
+ " folder import only: Use the full path towards the asset for determining the Album name",
+ myflag.BoolFlagFn(&app.UseFullPathAsAlbumName, false))
+ cmd.StringVar(&app.AlbumNamePathSeparator,
+ "album-name-path-separator",
+ " ",
+ " when use-full-path-album-name = true, determines how multiple (sub) folders, if any, will be joined")
cmd.BoolFunc(
"google-photos",
"Import GooglePhotos takeout zip files",
@@ -565,7 +575,7 @@ func (app *UpCmd) manageAssetAlbum(ctx context.Context, assetID string, a *brows
}
app.Jnl.Record(ctx, fileevent.UploadAddToAlbum, a, a.FileName, "album", album, "reason", "option -create-album-folder")
if !app.DryRun {
- err := app.AddToAlbum(ctx, assetID, browser.LocalAlbum{Title: album})
+ err := app.AddToAlbum(ctx, assetID, browser.LocalAlbum{Title: album, Path: a.FileName})
if err != nil {
app.Jnl.Record(ctx, fileevent.Error, a, a.FileName, "error", err.Error())
}
@@ -678,6 +688,9 @@ func (app *UpCmd) AddToAlbum(ctx context.Context, id string, album browser.Local
title := album.Title
if (app.GooglePhotos && (title == "" || app.CreateAlbumAfterFolder)) || app.UseFolderAsAlbumName {
title = filepath.Base(album.Path)
+ } else if !app.GooglePhotos && app.UseFullPathAsAlbumName {
+ // full path
+ title = strings.Replace(filepath.Dir(album.Path), "/", app.AlbumNamePathSeparator, -1)
}
l, exist := app.albums[title]
diff --git a/cmd/upload/upload_test.go b/cmd/upload/upload_test.go
index 47fdec50..9e548008 100644
--- a/cmd/upload/upload_test.go
+++ b/cmd/upload/upload_test.go
@@ -466,7 +466,51 @@ func TestUpload(t *testing.T) {
},
},
},
-
+ {
+ name: "folder and albums creation using full path",
+ args: []string{
+ "-create-album-folder",
+ "-use-full-path-album-name",
+ "TEST_DATA/Takeout2",
+ },
+ expectedAssets: []string{
+ "Google Photos/Photos from 2023/PXL_20231006_063528961.jpg",
+ "Google Photos/Photos from 2023/PXL_20231006_063000139.jpg",
+ "Google Photos/Sans titre(9)/PXL_20231006_063108407.jpg",
+ },
+ expectedAlbums: map[string][]string{
+ "Google Photos Photos from 2023": {
+ "Google Photos/Photos from 2023/PXL_20231006_063000139.jpg",
+ "Google Photos/Photos from 2023/PXL_20231006_063528961.jpg",
+ },
+ "Google Photos Sans titre(9)": {
+ "Google Photos/Sans titre(9)/PXL_20231006_063108407.jpg",
+ },
+ },
+ },
+ {
+ name: "folder and albums creation using full path and custom separator",
+ args: []string{
+ "-create-album-folder",
+ "-use-full-path-album-name",
+ "-album-name-path-separator= & ",
+ "TEST_DATA/Takeout2",
+ },
+ expectedAssets: []string{
+ "Google Photos/Photos from 2023/PXL_20231006_063528961.jpg",
+ "Google Photos/Photos from 2023/PXL_20231006_063000139.jpg",
+ "Google Photos/Sans titre(9)/PXL_20231006_063108407.jpg",
+ },
+ expectedAlbums: map[string][]string{
+ "Google Photos & Photos from 2023": {
+ "Google Photos/Photos from 2023/PXL_20231006_063000139.jpg",
+ "Google Photos/Photos from 2023/PXL_20231006_063528961.jpg",
+ },
+ "Google Photos & Sans titre(9)": {
+ "Google Photos/Sans titre(9)/PXL_20231006_063108407.jpg",
+ },
+ },
+ },
// // {
// // name: "google photo, homonyms, keep partner",
// // args: []string{
diff --git a/readme.md b/readme.md
index ac1e0555..e3fcc862 100644
--- a/readme.md
+++ b/readme.md
@@ -95,17 +95,19 @@ Use this command for uploading photos and videos from a local directory, a zippe
### Switches and options:
-| **Parameter** | **Description** | **Default value** |
-| ------------------------------------ | -------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- |
-| `-album="ALBUM NAME"` | Import assets into the Immich album `ALBUM NAME`. | |
-| `-dry-run` | Preview all actions as they would be done. | `FALSE` |
-| `-create-album-folder` | Generate immich albums after folder names. | `FALSE` |
-| `-create-stacks` | Stack jpg/raw or bursts. | `FALSE` |
-| `-stack-jpg-raw` | Control the stacking of jpg/raw photos. | `FALSE` |
-| `-stack-burst` | Control the stacking bursts. | `FALSE` |
-| `-select-types=".ext,.ext,.ext..."` | List of accepted extensions. | |
-| `-exclude-types=".ext,.ext,.ext..."` | List of excluded extensions. | |
-| `-when-no-date=FILE\|NOW` | When the date of take can't be determined, use the FILE's date or the current time NOW. | `FILE` |
+| **Parameter** | **Description** | **Default value** |
+|--------------------------------------|-------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------|
+| `-album="ALBUM NAME"` | Import assets into the Immich album `ALBUM NAME`. | |
+| `-dry-run` | Preview all actions as they would be done. | `FALSE` |
+| `-create-album-folder` | Generate immich albums after folder names. | `FALSE` |
+| `-use-full-path-album-name` | Use the full path to the file to determine the album name. | `FALSE` |
+| `-album-name-path-separator` | Determines how multiple (sub) folders, if any, will be joined | ` ` |
+| `-create-stacks` | Stack jpg/raw or bursts. | `FALSE` |
+| `-stack-jpg-raw` | Control the stacking of jpg/raw photos. | `FALSE` |
+| `-stack-burst` | Control the stacking bursts. | `FALSE` |
+| `-select-types=".ext,.ext,.ext..."` | List of accepted extensions. | |
+| `-exclude-types=".ext,.ext,.ext..."` | List of excluded extensions. | |
+| `-when-no-date=FILE\|NOW` | When the date of take can't be determined, use the FILE's date or the current time NOW. | `FILE` |
| `-exclude-files=pattern` | Ignore files based on a pattern. Case insensitive. Repeat the option for each pattern do you need. | `@eaDir/`
`@__thumb/`
`SYNOFILE_THUMB_*.*`
`Lightroom Catalog/`
`thumbnails/` |
### Date selection: