Snapshot manipulation?

Discussion in 'Chit-Chat' started by framednlv, Mar 26, 2014.

Share This Page

  1. framednlv

    framednlv Getting the hang of it

    Joined:
    Mar 17, 2014
    Messages:
    256
    Likes Received:
    69
    Does anyone have a way to manipulate snapshot JPG's with VB script or BAT file? They are buried deep into subfolders and I would like to rename using the date and time file was created & move them to a different folder and delete the old folders.

    Chris
     
    Last edited by a moderator: Mar 26, 2014
  2. bp2008

    bp2008 Staff Member

    Joined:
    Mar 10, 2014
    Messages:
    7,290
    Likes Received:
    3,772
    You'd have to be more specific. VB / Batch scripting is not my specialty but if it is simple enough I could whip up a little command-line application to do it.
     
  3. framednlv

    framednlv Getting the hang of it

    Joined:
    Mar 17, 2014
    Messages:
    256
    Likes Received:
    69
    It would need to search a specific folder and sub folders for all jpg files, then rename or save or move (move preferred) to a single folder using the creation date (YYYMMDDHHMMSS) + .jpg for the file name.

    Attached is a sample listing of the files saved for motion snapshots.

    I was able to find a couple of VBS script that came close but not quite. One would work if all the files were in one folder. The other one worked for all the sub directories but didn't change the name or remove the directories.


    Thanks,
    Chris
     

    Attached Files:

  4. bp2008

    bp2008 Staff Member

    Joined:
    Mar 10, 2014
    Messages:
    7,290
    Likes Received:
    3,772
    I built a command line application for you which does what you asked for (more or less). Let me know if it works as intended or if you need a change.

    Update: Now on github: bp2008/ImageOrganizer

    Usage (this shows if you run the program without any arguments):

    Code:
    Copies files from the source directory and child directories,
    consolidating them in the target directory and renaming the
    files to the format yyyyMMddHHmmssfff + .extension where the
    timestamp is the last modified date's year, month, day, hour,
    minute, second, millisecond.
    
            Note: Files will not be overwritten.  If a file
            already exists, the new file will have a space and an
            identifying number will be appended to the timestamp
            in the file name (e.g. 20140408010101000.jpg and
            20140408010101000 2.jpg and 20140408010101000 3.jpg)
    
    Usage: ImageOrganizer source target [/C] [/M] [/E:Extension1[/Extension2][/Extension3]...]
    
            /C      Names the files based on creation time instead of modified time.
            /M      Moves the files instead of only copying them.
            /E:     Specify the extension(s) of the files to move or copy.
                    If unspecified, only jpg files will be affected.
    
                    Example: /E:jpg/jpeg/bmp/png/gif/webp/raw

    C# Source code targetting .NET 3.5 Client Profile:
    Code:
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.IO;
    
    namespace ImageOrganizer
    {
        class Program
        {
            static void Main(string[] args)
            {
                try
                {
                    if (args.Length >= 2)
                    {
                        DirectoryInfo diSource = new DirectoryInfo(args[0]);
                        DirectoryInfo diTarget = new DirectoryInfo(args[1]);
    
                        bool move = false;
                        bool creationTime = false;
                        string filter = "jpg";
                        for (int i = 2; i < args.Length; i++)
                        {
                            if (args[i] == "/M")
                                move = true;
                            else if (args[i] == "/C")
                                creationTime = true;
                            else if (args[i].StartsWith("/E:"))
                                filter = args[i].Substring(3);
                        }
                        HashSet<string> extensions = new HashSet<string>(filter.Split('/'));
                        FileInfo[] sources = diSource.GetFiles("*", SearchOption.AllDirectories);
                        if (!diTarget.Exists)
                            Directory.CreateDirectory(diTarget.FullName);
                        string targetDirNormalized = diTarget.FullName.TrimEnd('\\', '/') + "/";
                        foreach(FileInfo fi in sources)
                            if (filter.Contains(fi.Extension.StartsWith(".") ? fi.Extension.Substring(1) : fi.Extension))
                            {
                                string timestamp = (creationTime ? fi.CreationTime : fi.LastWriteTime).ToString("yyyyMMddHHmmssfff");
                                int counter = 1;
                                string fileName = GetFileName(targetDirNormalized, timestamp, fi.Extension, counter);
                                while (File.Exists(fileName))
                                    fileName = GetFileName(targetDirNormalized, timestamp, fi.Extension, ++counter);
                                if (move)
                                    fi.MoveTo(fileName);
                                else
                                    fi.CopyTo(fileName, false);
                            }
                    }
                    else
                    {
                        OutputUsage();
                    }
    
                }
                catch (Exception ex)
                {
                    ReportError(ex);
                }
            }
    
            private static string GetFileName(string targetDirNormalized, string timestamp, string extension, int counter)
            {
                if (counter < 2)
                    return targetDirNormalized + timestamp + extension;
                return targetDirNormalized + timestamp + " " + counter + extension;
            }
    
            private static void ReportError(Exception ex)
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine(ex.ToString());
                Console.ResetColor();
            }
    
            private static void OutputUsage()
            {
                FileInfo fi = new FileInfo(Environment.GetCommandLineArgs()[0]);
                Console.WriteLine();
                Console.WriteLine("Copies files from the source directory and child directories, ");
                Console.WriteLine("consolidating them in the target directory and renaming the ");
                Console.WriteLine("files to the format yyyyMMddHHmmssfff + .extension where the ");
                Console.WriteLine("timestamp is the last modified date's year, month, day, hour, ");
                Console.WriteLine("minute, second, millisecond.");
                Console.WriteLine();
                Console.WriteLine("\tNote: Files will not be overwritten.  If a file ");
                Console.WriteLine("\talready exists, the new file will have a space and an ");
                Console.WriteLine("\tidentifying number will be appended to the timestamp ");
                Console.WriteLine("\tin the file name (e.g. 20140408010101000.jpg and ");
                Console.WriteLine("\t20140408010101000 2.jpg and 20140408010101000 3.jpg)");
                Console.WriteLine();
                Console.WriteLine("Usage: " + fi.Name.Substring(0, fi.Name.Length - fi.Extension.Length) + " source target [/C] [/M] [/E:Extension1[/Extension2][/Extension3]...]");
                Console.WriteLine();
                Console.WriteLine("\t/C\tNames the files based on creation time instead of modified time.");
                Console.WriteLine("\t/M\tMoves the files instead of only copying them.");
                Console.WriteLine("\t/E:\tSpecify the extension(s) of the files to move or copy.");
                Console.WriteLine("\t\tIf unspecified, only jpg files will be affected.");
                Console.WriteLine();
                Console.WriteLine("\t\tExample: /E:jpg/jpeg/bmp/png/gif/webp/raw");
            }
        }
    }
    
     
    Last edited: Sep 12, 2018
    framednlv likes this.
  5. framednlv

    framednlv Getting the hang of it

    Joined:
    Mar 17, 2014
    Messages:
    256
    Likes Received:
    69
    BP Thanks,
    I'll give it a go later tonight.

    How do you set the source directory?
    How do you set the target directory?
     
    Last edited by a moderator: Apr 8, 2014
  6. bp2008

    bp2008 Staff Member

    Joined:
    Mar 10, 2014
    Messages:
    7,290
    Likes Received:
    3,772
    Just like any command line application, look at the usage line. Source dir is the first argument. Target dir is the second argument. Then you can add additional arguments if you want to change the behavior.

    Code:
    Usage: ImageOrganizer source target [/C] [/M] [/E:Extension1[/Extension2][/Extension3]...]
    
            /C      Names the files based on creation time instead of modified time.
            /M      Moves the files instead of only copying them.
            /E:     Specify the extension(s) of the files to move or copy.
                    If unspecified, only jpg files will be affected.
    
                    Example: /E:jpg/jpeg/bmp/png/gif/webp/raw
    Here are some examples:

    Code:
    ImageOrganizer "C:\Unorganized Images" OrganizedImages
    This uses an absolute path for the source, and I quoted it because it contains a space. The folder named Unorganized Images in the root of drive C is the source. The target directory is a relative path pointing at a folder named OrganizedImages in the current working directory.



    Code:
    ImageOrganizer C:\Unorganized "C:\Image Output\OrganizedImages"
    Both paths are absolute paths in this case.

    Code:
    ImageOrganizer input output
    Both paths are relative paths.

    Code:
    ImageOrganizer input output /C
    Files are named based on the Creation Date instead of the last modified date.

    Code:
    ImageOrganizer input output /M
    Files are moved instead of copied.

    Code:
    ImageOrganizer input output /E:png/gif/jpg
    png, gif, and jpg files are copied. (if you don't include this argument, then only jpg files are copied)

    Code:
    ImageOrganizer input output /C /M /E:png/gif/jpg
    png, gif, and jpg files are moved and named based on creation date
     
    framednlv likes this.
  7. framednlv

    framednlv Getting the hang of it

    Joined:
    Mar 17, 2014
    Messages:
    256
    Likes Received:
    69
    That works great!!!
    I'll set it up at home and run it every hour (using the move switch).

    Thanks.
    Chris
     
  8. framednlv

    framednlv Getting the hang of it

    Joined:
    Mar 17, 2014
    Messages:
    256
    Likes Received:
    69
    It worked fine at work but not at home. Turns out I can't have the ImageOrganizer.exe in the same folder as the sorce directory.
     
  9. framednlv

    framednlv Getting the hang of it

    Joined:
    Mar 17, 2014
    Messages:
    256
    Likes Received:
    69
    I keep getting an error:

    Code:
    C:\record>ImageOrganizer C:\record\TGC2GW26300052 C:\record\dahua-6mm /C /M /E:jpg
    System.ArgumentOutOfRangeException: startIndex cannot be larger than length of
    tring.
    Parameter name: startIndex
       at System.String.InternalSubStringWithChecks(Int32 startIndex, Int32 length,
    Boolean fAlwaysCopy)
       at ImageOrganizer.Program.Main(String[] args)
    
    Any Idea?
     
  10. bp2008

    bp2008 Staff Member

    Joined:
    Mar 10, 2014
    Messages:
    7,290
    Likes Received:
    3,772
    Hah. You definitely found a bug. I will investigate tomorrow and also check out the 'same folder as the source directory' problem. Can you give more details on that?
     
  11. framednlv

    framednlv Getting the hang of it

    Joined:
    Mar 17, 2014
    Messages:
    256
    Likes Received:
    69
    The camera makes a file called DVRWorkDirectory (no extension) in the source folder. Once this file is deleted it seems to work.
    My bat file:
    Code:
    SET date=%date:~10,4%-%date:~4,2%-%date:~7,2%
    md dahua-6mm\%date%
    del TGC2GW26300052\DVRWorkDirectory
    c:\ImageOrganizer.exe C:\record\TGC2GW26300052 C:\record\dahua-6mm\%date% /C /M /E:jpg
    
    I have the task scheduler running every hour. Seems like a lot of messing around to fix the excessive folder structure.
     
  12. bp2008

    bp2008 Staff Member

    Joined:
    Mar 10, 2014
    Messages:
    7,290
    Likes Received:
    3,772
    Here is an updated version that should have that bug fixed. I expect you had a file with no extension in that source directory.

    Update: Now on github: bp2008/ImageOrganizer
     
    Last edited: Sep 12, 2018
  13. framednlv

    framednlv Getting the hang of it

    Joined:
    Mar 17, 2014
    Messages:
    256
    Likes Received:
    69
    The updated version doen't error out but it does copy the extentionless file to the target directory. Any way to filter that out?

    .... And thanks for all the work on this. Sure make viewing the days events fast.
     
  14. bp2008

    bp2008 Staff Member

    Joined:
    Mar 10, 2014
    Messages:
    7,290
    Likes Received:
    3,772
    Sure enough.

    Update: Now on github: bp2008/ImageOrganizer

    Now it will only copy extensionless files if the complete file name is one of the extensions you are looking for.
     
    Last edited: Sep 12, 2018
    framednlv likes this.
  15. framednlv

    framednlv Getting the hang of it

    Joined:
    Mar 17, 2014
    Messages:
    256
    Likes Received:
    69
    Thanks.
    Works great.....
    Now I need to tweak the motion detection for my cameras.
     
  16. nanobot

    nanobot n3wb

    Joined:
    Sep 12, 2018
    Messages:
    2
    Likes Received:
    0
    Location:
    romania
    You can upload this script one more time please

    Thanks,
    jojo
     
  17. bp2008

    bp2008 Staff Member

    Joined:
    Mar 10, 2014
    Messages:
    7,290
    Likes Received:
    3,772
  18. framednlv

    framednlv Getting the hang of it

    Joined:
    Mar 17, 2014
    Messages:
    256
    Likes Received:
    69
    I changed to power shell. This is what I ended up with:
    Code:
    function SortPictures
    {
    Set-Location \\NAS\Record
    Set-Location \\Router\hdd1
    #rename files
    $files = get-childitem -path $folder -recurse -Include "*.jpeg", "*.jpg" | where { -not $_.PSIsContainer }
    [datetime]$dirDate = New-Object DateTime
    $i=1000
    foreach ($file In $files) {
    $i = $i + 1
    
        $strDate = $file.Name.substring(0,8)
    
        if (-Not [DateTime]::TryParseExact($strDate, "yyyy-MM-dd",
            [System.Globalization.CultureInfo]::InvariantCulture,
            [System.Globalization.DateTimeStyles]::None, [ref]$dirDate)) {
            $newName = $file.lastwritetime.tostring("yyyy-MM-dd HHmmss") +$i + ".jpg"
            echo $newName
            echo Item -path $file.Fullname -newname $folder + "\"+ $newName
            Rename-Item  -literalpath $file.Fullname -newname  $newName
            #Rename-Item -path $file.Fullname -newname $newName
        } 
    }
    #move files
    get-childItem $folder -recurse | where {$_.length -eq 0} | remove-Item
    $files = Get-ChildItem $folder  -Recurse | where {!$_.PsIsContainer}
    $files
    foreach ($file in $files)
    {
    $NFolder=$file.LastWriteTime.ToString("yyyy-MM-dd")
    $file.Name
    $NFolder
    $Directory = $targetPath + "\" + $NFolder
    $Directory2 = $targetPath2 #+ "\" + $NFolder
    
    #added to echo folder
    
    write-host -fore $nColor $folder
    if (!(Test-Path $Directory))
    {
    New-Item $directory -type directory
    }
    if (!(Test-Path $Directory2))
    {
    New-Item $directory2 -type directory
    }
    $file | Copy-Item -Destination $Directory2
    $file | Move-Item -Destination $Directory
    }
    #empty temp folder
    Get-ChildItem $folder -recurse | Where {$_.PSIsContainer -and @(Get-ChildItem -Lit $_.Fullname -r | Where {!$_.PSIsContainer}).Length -eq 0}  | Remove-Item -recurse -WhatIf
    Get-ChildItem $folder -recurse | Where {$_.PSIsContainer -and @(Get-ChildItem -Lit $_.Fullname -r | Where {!$_.PSIsContainer}).Length -eq 0}  | Remove-Item -recurse #-WhatIf
    }
    
    
    #add camera snapshot location in the folder
    #add target path to copy to
    #add target path2 to move files
    
    $nColor = "green"
    $folder = "\\router\hdd1\Camera_01"
    $targetPath = "\\NAS\Record\Camera_01"
    $targetpath2 = "C:\Users\dad\Documents\sorting\camera\Camera_01\"
    SortPictures
    
    $nColor = "Magenta"
    $folder = "\\router\hdd1\Camera_02"
    $targetPath = "\\NAS\Record\Camera_02"
    $targetpath2 = "C:\Users\dad\Documents\sorting\camera\Camera_02\"
    SortPictures
    
    $nColor = "Cyan"
    $folder = "\\router\hdd1\Camera_03"
    $targetPath = "\\NAS\Record\Camera_03"
    $targetpath2 = "C:\Users\dad\Documents\sorting\camera\Camera_03\"
    SortPictures
    
    $nColor = "blue"
    $folder = "\\router\hdd1\Camera_04"
    $targetPath = "\\NAS\Record\Camera_04"
    $targetpath2 = "C:\Users\dad\Documents\sorting\camera\Camera_04\"
    SortPictures
    
    $nColor = "red"
    $folder = "\\router\hdd1\Camera_05"
    $targetPath = "\\NAS\Record\Camera_05"
    $targetpath2 = "C:\Users\dad\Documents\sorting\camera\Camera_05\"
    SortPictures
    
    $nColor = "red"
    $folder = "\\router\hdd1\Camera_06"
    $targetPath = "\\NAS\Record\Camera_06"
    $targetpath2 = "C:\Users\dad\Documents\sorting\camera\Camera_06\"
    SortPictures
    
    $nColor = "Yellow"
    $folder = "\\router\hdd1\Camera_07"
    $targetPath = "\\NAS\Record\Camera_07"
    $targetpath2 = "C:\Users\dad\Documents\sorting\camera\Camera_07\"
    SortPictures
    
    $nColor = "Green"
    $folder = "\\router\hdd1\Camera_08"
    $targetPath = "\\NAS\Record\Camera_08"
    $targetpath2 = "C:\Users\dad\Documents\sorting\camera\Camera_08\"
    SortPictures
    
    explorer.exe "C:\Users\dad\Documents\sorting\camera"
    
    

    Since I don't do programming, it took me a while to put this together from the internet.
    I set this up to rename and copy the files to my laptop then move the files to my NAS.
    To use it set the $folder to the location of the pictures, set $targetPath to move the files and set $targetpath2 to copy the files. You will also need to setup PowerShell to run scripts, search 'How to enable execution of PowerShell scripts'.

    Feel free to comment on the program as I am not the good at hacking together scripts.
     
  19. nanobot

    nanobot n3wb

    Joined:
    Sep 12, 2018
    Messages:
    2
    Likes Received:
    0
    Location:
    romania
    i will give a try and many thanks for the prompt reply!
     
  20. gregbert

    gregbert Young grasshopper

    Joined:
    Jan 9, 2017
    Messages:
    52
    Likes Received:
    22
    Location:
    Lewisville, TX
    Python is a pretty fun language to use and could do this pretty easily. A bit of a learning curve, but tons of examples out there to get started and something like this wouldn't require much more than learning a basic python app along with how to process files/folders.