feat: --selected mode — process individual files (context menu + SendTo)
This commit is contained in:
1 parent
33c33d08f0
commit
051d12eb3c
5 files changed
+167
-95
No files matched your search
@@ -72,7 +72,14 @@ install.bat
|
||||
uninstall-context-menu.bat
|
||||
```
|
||||
|
||||
После установки в контекстном меню два пункта:
|
||||
- **«Raskidator-3000»** — сортировка (реальное перемещение)
|
||||
- **«Raskidator-3000 (dry-run)»** — только показать что будет перемещено
|
||||
- **Работает в библиотеках** (Pictures, Music, Videos, Documents)
|
||||
После установки:
|
||||
|
||||
| Действие | Результат |
|
||||
|----------|-----------|
|
||||
| **ПКМ на папке** → Raskidator-3000 | Сортировка всей папки |
|
||||
| **ПКМ на папке** → Raskidator-3000 (dry-run) | Только показать что будет |
|
||||
| **ПКМ на файле** → Raskidator-3000 | Сортировать только этот файл |
|
||||
| **Выделить файлы** → Отправить → Raskidator-3000 | Сортировать только выделенные файлы |
|
||||
| Работает в библиотеках (Pictures, Music, Videos) | |
|
||||
|
||||
При сортировке отдельных файлов (`--selected`) лимит `MAX_FILES` игнорируется — обрабатываются все переданные файлы.
|
||||
+63
-27
@@ -18,54 +18,90 @@ echo.
|
||||
set "BAT_PATH=%BAT_DIR%\raskidator.bat"
|
||||
set "ICON=%BAT_DIR%\raskidator.bat,0"
|
||||
|
||||
:: Directory\Background\shell - right-click in empty folder space
|
||||
echo [1/3] Adding to folder background context menu...
|
||||
:: ── 1. Папки (правая кнопка на папке) ─────────────────────────────
|
||||
echo [1/4] Folder context menu...
|
||||
|
||||
:: Обычный запуск
|
||||
reg add "HKEY_CLASSES_ROOT\Directory\Background\shell\Raskidator3000" /ve /t REG_SZ /d "Raskidator-3000" /f
|
||||
reg add "HKEY_CLASSES_ROOT\Directory\Background\shell\Raskidator3000" /v Icon /t REG_SZ /d "%ICON%" /f
|
||||
reg add "HKEY_CLASSES_ROOT\Directory\Background\shell\Raskidator3000\command" /ve /t REG_SZ /d "\"%BAT_PATH%\" \"%%V\"" /f
|
||||
|
||||
:: Пробный запуск (dry-run)
|
||||
reg add "HKEY_CLASSES_ROOT\Directory\Background\shell\Raskidator3000DryRun" /ve /t REG_SZ /d "Raskidator-3000 (dry-run)" /f
|
||||
reg add "HKEY_CLASSES_ROOT\Directory\Background\shell\Raskidator3000DryRun" /v Icon /t REG_SZ /d "%ICON%" /f
|
||||
reg add "HKEY_CLASSES_ROOT\Directory\Background\shell\Raskidator3000DryRun\command" /ve /t REG_SZ /d "\"%BAT_PATH%\" --dry-run \"%%V\"" /f
|
||||
|
||||
echo [+] Directory\Background - done (2 entries)
|
||||
echo.
|
||||
|
||||
:: Directory\shell - right-click on folder
|
||||
echo [2/3] Adding to folder right-click menu...
|
||||
|
||||
reg add "HKEY_CLASSES_ROOT\Directory\shell\Raskidator3000" /ve /t REG_SZ /d "Raskidator-3000" /f
|
||||
reg add "HKEY_CLASSES_ROOT\Directory\shell\Raskidator3000" /v Icon /t REG_SZ /d "%ICON%" /f
|
||||
reg add "HKEY_CLASSES_ROOT\Directory\shell\Raskidator3000\command" /ve /t REG_SZ /d "\"%BAT_PATH%\" \"%%1\"" /f
|
||||
|
||||
reg add "HKEY_CLASSES_ROOT\Directory\shell\Raskidator3000DryRun" /ve /t REG_SZ /d "Raskidator-3000 (dry-run)" /f
|
||||
reg add "HKEY_CLASSES_ROOT\Directory\shell\Raskidator3000DryRun" /v Icon /t REG_SZ /d "%ICON%" /f
|
||||
reg add "HKEY_CLASSES_ROOT\Directory\shell\Raskidator3000DryRun\command" /ve /t REG_SZ /d "\"%BAT_PATH%\" --dry-run \"%%1\"" /f
|
||||
|
||||
echo [+] Directory\shell - done (2 entries)
|
||||
echo.
|
||||
|
||||
:: LibraryFolder\Background - Pictures, Music, Videos...
|
||||
echo [3/3] Adding to libraries (Pictures, Music, Videos)...
|
||||
|
||||
reg add "HKEY_CLASSES_ROOT\LibraryFolder\Background\shell\Raskidator3000" /ve /t REG_SZ /d "Raskidator-3000" /f
|
||||
reg add "HKEY_CLASSES_ROOT\LibraryFolder\Background\shell\Raskidator3000" /v Icon /t REG_SZ /d "%ICON%" /f
|
||||
reg add "HKEY_CLASSES_ROOT\LibraryFolder\Background\shell\Raskidator3000\command" /ve /t REG_SZ /d "\"%BAT_PATH%\" \"%%V\"" /f
|
||||
|
||||
:: Пробный запуск (dry-run)
|
||||
reg add "HKEY_CLASSES_ROOT\Directory\Background\shell\Raskidator3000DryRun" /ve /t REG_SZ /d "Raskidator-3000 (dry-run)" /f
|
||||
reg add "HKEY_CLASSES_ROOT\Directory\Background\shell\Raskidator3000DryRun" /v Icon /t REG_SZ /d "%ICON%" /f
|
||||
reg add "HKEY_CLASSES_ROOT\Directory\Background\shell\Raskidator3000DryRun\command" /ve /t REG_SZ /d "\"%BAT_PATH%\" --dry-run \"%%V\"" /f
|
||||
|
||||
reg add "HKEY_CLASSES_ROOT\Directory\shell\Raskidator3000DryRun" /ve /t REG_SZ /d "Raskidator-3000 (dry-run)" /f
|
||||
reg add "HKEY_CLASSES_ROOT\Directory\shell\Raskidator3000DryRun" /v Icon /t REG_SZ /d "%ICON%" /f
|
||||
reg add "HKEY_CLASSES_ROOT\Directory\shell\Raskidator3000DryRun\command" /ve /t REG_SZ /d "\"%BAT_PATH%\" --dry-run \"%%1\"" /f
|
||||
|
||||
reg add "HKEY_CLASSES_ROOT\LibraryFolder\Background\shell\Raskidator3000DryRun" /ve /t REG_SZ /d "Raskidator-3000 (dry-run)" /f
|
||||
reg add "HKEY_CLASSES_ROOT\LibraryFolder\Background\shell\Raskidator3000DryRun" /v Icon /t REG_SZ /d "%ICON%" /f
|
||||
reg add "HKEY_CLASSES_ROOT\LibraryFolder\Background\shell\Raskidator3000DryRun\command" /ve /t REG_SZ /d "\"%BAT_PATH%\" --dry-run \"%%V\"" /f
|
||||
|
||||
echo [+] LibraryFolder\Background - done (2 entries)
|
||||
echo [+] Folder context menu — done
|
||||
echo.
|
||||
|
||||
:: ── 2. Файлы (правая кнопка на 1 файле) ──────────────────────────
|
||||
echo [2/4] File context menu...
|
||||
|
||||
reg add "HKEY_CLASSES_ROOT\*\shell\Raskidator3000" /ve /t REG_SZ /d "Raskidator-3000" /f
|
||||
reg add "HKEY_CLASSES_ROOT\*\shell\Raskidator3000" /v Icon /t REG_SZ /d "%ICON%" /f
|
||||
reg add "HKEY_CLASSES_ROOT\*\shell\Raskidator3000\command" /ve /t REG_SZ /d "\"%BAT_PATH%\" --selected \"%%1\"" /f
|
||||
|
||||
reg add "HKEY_CLASSES_ROOT\*\shell\Raskidator3000DryRun" /ve /t REG_SZ /d "Raskidator-3000 (dry-run)" /f
|
||||
reg add "HKEY_CLASSES_ROOT\*\shell\Raskidator3000DryRun" /v Icon /t REG_SZ /d "%ICON%" /f
|
||||
reg add "HKEY_CLASSES_ROOT\*\shell\Raskidator3000DryRun\command" /ve /t REG_SZ /d "\"%BAT_PATH%\" --selected --dry-run \"%%1\"" /f
|
||||
|
||||
echo [+] File context menu — done
|
||||
echo.
|
||||
|
||||
:: ── 3. SendTo (несколько выделенных файлов) ──────────────────────
|
||||
echo [3/4] SendTo (multi-file)..
|
||||
|
||||
set "SENDTO=%APPDATA%\Microsoft\Windows\SendTo"
|
||||
|
||||
:: Основной
|
||||
del "%SENDTO%\Raskidator-3000.bat" 2>nul
|
||||
> "%SENDTO%\Raskidator-3000.bat" (
|
||||
echo @echo off
|
||||
echo chcp 65001 ^>nul
|
||||
echo call "%BAT_PATH%" --selected %%*
|
||||
)
|
||||
|
||||
:: Пробный (dry-run)
|
||||
del "%SENDTO%\Raskidator-3000 (dry-run).bat" 2>nul
|
||||
> "%SENDTO%\Raskidator-3000 (dry-run).bat" (
|
||||
echo @echo off
|
||||
echo chcp 65001 ^>nul
|
||||
echo call "%BAT_PATH%" --selected --dry-run %%*
|
||||
)
|
||||
|
||||
echo [+] SendTo — done
|
||||
echo.
|
||||
|
||||
:: ── 4. Удаление старых версий ──────────────────────────────────────
|
||||
echo [4/4] Cleaning up old entries...
|
||||
|
||||
reg delete "HKEY_CLASSES_ROOT\*\shell\Raskidator3000" /f >nul 2>&1
|
||||
reg delete "HKEY_CLASSES_ROOT\*\shell\Raskidator3000DryRun" /f >nul 2>&1
|
||||
|
||||
echo [+] Cleanup — done
|
||||
echo.
|
||||
|
||||
echo ========================================
|
||||
echo Installation complete!
|
||||
echo Right-click any folder ->
|
||||
echo Raskidator-3000 — сортировка
|
||||
echo Raskidator-3000 (dry-run) — пробный запуск
|
||||
echo.
|
||||
echo ПКМ на папке — Raskidator-3000
|
||||
echo ПКМ на файле — Raskidator-3000
|
||||
echo Отправить ^> файлы — Raskidator-3000 (любое кол-во)
|
||||
echo ========================================
|
||||
pause
|
||||
+55
-24
@@ -317,6 +317,7 @@ def organize(
|
||||
group_by: str = 'day',
|
||||
quiet: bool = False,
|
||||
max_files: int | None = None,
|
||||
selected_files: list[Path] | None = None,
|
||||
) -> int:
|
||||
"""Scan *folder* and sort images into year/month[/day] subfolders.
|
||||
|
||||
@@ -327,10 +328,13 @@ def organize(
|
||||
return 1
|
||||
|
||||
# ── Scan ────────────────────────────────────────────────────────────────
|
||||
files: list[Path] = [
|
||||
f for f in folder.iterdir()
|
||||
if f.is_file() and f.suffix.lower() in EXTENSIONS
|
||||
]
|
||||
if selected_files is not None:
|
||||
files = [f for f in selected_files if f.suffix.lower() in EXTENSIONS]
|
||||
else:
|
||||
files: list[Path] = [
|
||||
f for f in folder.iterdir()
|
||||
if f.is_file() and f.suffix.lower() in EXTENSIONS
|
||||
]
|
||||
files.sort()
|
||||
if max_files is not None and len(files) > max_files:
|
||||
print(_c(f' First {max_files} of {len(files)} files '
|
||||
@@ -626,10 +630,16 @@ def main() -> None:
|
||||
add_help=True,
|
||||
)
|
||||
parser.add_argument(
|
||||
'path',
|
||||
nargs='?',
|
||||
'paths',
|
||||
nargs='*',
|
||||
default=None,
|
||||
help='Folder to scan (default: current directory)',
|
||||
help='Folder to scan, or file(s) with --selected',
|
||||
)
|
||||
parser.add_argument(
|
||||
'--selected',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help='Process specified files instead of scanning a folder',
|
||||
)
|
||||
parser.add_argument(
|
||||
'--no-color',
|
||||
@@ -666,23 +676,44 @@ def main() -> None:
|
||||
# If --max-files not set, use MAX_FILES constant
|
||||
max_files = args.max_files if args.max_files is not None else MAX_FILES
|
||||
|
||||
folder = Path(args.path) if args.path else Path.cwd()
|
||||
print(_c('Raskidator-3000', _BOLD, no_color=args.no_color))
|
||||
print(f' Folder: {folder.resolve()}')
|
||||
if args.dry_run:
|
||||
print(_c(' Mode: DRY-RUN', _CYAN, no_color=args.no_color))
|
||||
if max_files:
|
||||
print(f' Max files: {max_files}')
|
||||
print()
|
||||
|
||||
rc = organize(
|
||||
folder,
|
||||
dry_run=args.dry_run,
|
||||
no_color=args.no_color,
|
||||
group_by=args.group_by,
|
||||
quiet=args.quiet,
|
||||
max_files=max_files,
|
||||
)
|
||||
if args.selected:
|
||||
# Process specified files (from SendTo or file selection)
|
||||
file_paths = [Path(p) for p in args.paths if Path(p).is_file()]
|
||||
if not file_paths:
|
||||
print(_c(' No valid files specified.', _YELLOW, no_color=args.no_color))
|
||||
sys.exit(1)
|
||||
max_files = len(file_paths) # process exactly the selected files
|
||||
print(_c('Raskidator-3000', _BOLD, no_color=args.no_color))
|
||||
print(f' Selected files: {len(file_paths)}')
|
||||
if args.dry_run:
|
||||
print(_c(' Mode: DRY-RUN', _CYAN, no_color=args.no_color))
|
||||
print()
|
||||
rc = organize(
|
||||
file_paths[0].parent, # use parent folder as base
|
||||
dry_run=args.dry_run,
|
||||
no_color=args.no_color,
|
||||
group_by=args.group_by,
|
||||
quiet=args.quiet,
|
||||
max_files=max_files,
|
||||
selected_files=file_paths,
|
||||
)
|
||||
else:
|
||||
folder = Path(args.paths[0]) if args.paths else Path.cwd()
|
||||
print(_c('Raskidator-3000', _BOLD, no_color=args.no_color))
|
||||
print(f' Folder: {folder.resolve()}')
|
||||
if args.dry_run:
|
||||
print(_c(' Mode: DRY-RUN', _CYAN, no_color=args.no_color))
|
||||
if max_files:
|
||||
print(f' Max files: {max_files}')
|
||||
print()
|
||||
rc = organize(
|
||||
folder,
|
||||
dry_run=args.dry_run,
|
||||
no_color=args.no_color,
|
||||
group_by=args.group_by,
|
||||
quiet=args.quiet,
|
||||
max_files=max_files,
|
||||
)
|
||||
sys.exit(rc)
|
||||
|
||||
|
||||
|
||||
+21
-30
@@ -10,41 +10,32 @@ echo.
|
||||
:: Сохраняем путь к папке с батником ДО shift (shift меняет %0)
|
||||
set "BAT_DIR=%~dp0"
|
||||
|
||||
:: Определяем режим (--dry-run или обычный)
|
||||
:: Определяем режимы
|
||||
set "DRY="
|
||||
if /i "%~1"=="--dry-run" (
|
||||
set "DRY=--dry-run"
|
||||
shift
|
||||
)
|
||||
set "SELECTED="
|
||||
if /i "%~1"=="--selected" set "SELECTED=--selected" & shift
|
||||
if /i "%~1"=="--dry-run" set "DRY=--dry-run" & shift
|
||||
|
||||
:: Определяем папку, которую обрабатываем
|
||||
if "%~1"=="" (
|
||||
set "TARGET=%CD%"
|
||||
if not "%SELECTED%"=="" (
|
||||
:: Режим выбранных файлов (SendTo / контекстное меню)
|
||||
echo Выбранные файлы: %*
|
||||
echo.
|
||||
python "%BAT_DIR%organize.py" --selected %DRY% %*
|
||||
if %errorlevel% equ 0 goto :end
|
||||
py -3 "%BAT_DIR%organize.py" --selected %DRY% %*
|
||||
if %errorlevel% equ 0 goto :end
|
||||
) else (
|
||||
set "TARGET=%~1"
|
||||
:: Режим папки
|
||||
if "%~1"=="" (set "TARGET=%CD%") else (set "TARGET=%~1")
|
||||
echo Папка: %TARGET%
|
||||
if not "%DRY%"=="" echo Режим: ПРОБНЫЙ (dry-run)
|
||||
echo.
|
||||
python "%BAT_DIR%organize.py" %DRY% "%TARGET%"
|
||||
if %errorlevel% equ 0 goto :end
|
||||
py -3 "%BAT_DIR%organize.py" %DRY% "%TARGET%"
|
||||
if %errorlevel% equ 0 goto :end
|
||||
)
|
||||
|
||||
echo Папка: %TARGET%
|
||||
if not "%DRY%"=="" echo Режим: ПРОБНЫЙ (dry-run)
|
||||
echo.
|
||||
|
||||
:: Проверяем, существует ли скрипт
|
||||
if exist "%BAT_DIR%organize.py" (
|
||||
set "SCRIPT=%BAT_DIR%organize.py"
|
||||
) else (
|
||||
echo [ОШИБКА] Не найден organize.py рядом с батником.
|
||||
echo Ожидаемый путь: %BAT_DIR%organize.py
|
||||
goto :end
|
||||
)
|
||||
|
||||
:: Пробуем python (наиболее распространён)
|
||||
python "%SCRIPT%" %DRY% "%TARGET%"
|
||||
if %errorlevel% equ 0 goto :end
|
||||
|
||||
:: Если python не сработал — пробуем py -3 (Python Launcher)
|
||||
py -3 "%SCRIPT%" %DRY% "%TARGET%"
|
||||
if %errorlevel% equ 0 goto :end
|
||||
|
||||
:: Если оба не сработали
|
||||
echo.
|
||||
echo [ОШИБКА] Python не найден. Установи Python с python.org
|
||||
|
||||
+17
-10
@@ -8,22 +8,29 @@ echo Raskidator-3000
|
||||
echo ========================================
|
||||
echo.
|
||||
|
||||
echo [1/3] Removing from folder background context menu...
|
||||
echo [1/4] Removing from folder context menus...
|
||||
reg delete "HKEY_CLASSES_ROOT\Directory\Background\shell\Raskidator3000" /f >nul 2>&1
|
||||
reg delete "HKEY_CLASSES_ROOT\Directory\Background\shell\Raskidator3000DryRun" /f >nul 2>&1
|
||||
if %errorlevel% equ 0 (echo [+] Directory\Background - removed) else (echo [+] Directory\Background - done)
|
||||
echo.
|
||||
|
||||
echo [2/3] Removing from folder right-click menu...
|
||||
reg delete "HKEY_CLASSES_ROOT\Directory\shell\Raskidator3000" /f >nul 2>&1
|
||||
reg delete "HKEY_CLASSES_ROOT\Directory\shell\Raskidator3000DryRun" /f >nul 2>&1
|
||||
if %errorlevel% equ 0 (echo [+] Directory\shell - removed) else (echo [+] Directory\shell - done)
|
||||
echo.
|
||||
|
||||
echo [3/3] Removing from libraries (Pictures, Music, Videos)...
|
||||
reg delete "HKEY_CLASSES_ROOT\LibraryFolder\Background\shell\Raskidator3000" /f >nul 2>&1
|
||||
reg delete "HKEY_CLASSES_ROOT\LibraryFolder\Background\shell\Raskidator3000DryRun" /f >nul 2>&1
|
||||
if %errorlevel% equ 0 (echo [+] LibraryFolder\Background - removed) else (echo [+] LibraryFolder\Background - done)
|
||||
echo [+] Folder menus — done
|
||||
echo.
|
||||
|
||||
echo [2/4] Removing from file context menus...
|
||||
reg delete "HKEY_CLASSES_ROOT\*\shell\Raskidator3000" /f >nul 2>&1
|
||||
reg delete "HKEY_CLASSES_ROOT\*\shell\Raskidator3000DryRun" /f >nul 2>&1
|
||||
echo [+] File menus — done
|
||||
echo.
|
||||
|
||||
echo [3/4] Removing SendTo entries...
|
||||
del "%APPDATA%\Microsoft\Windows\SendTo\Raskidator-3000.bat" 2>nul
|
||||
del "%APPDATA%\Microsoft\Windows\SendTo\Raskidator-3000 (dry-run).bat" 2>nul
|
||||
echo [+] SendTo — done
|
||||
echo.
|
||||
|
||||
echo [4/4] Cleanup complete
|
||||
echo.
|
||||
|
||||
echo ========================================
|
||||
|
||||
Reference in new issue
Block a user