Wanna help me write a windows or linux script?

I’ve been doing some research but unfortunately I’m just too much of a novice to tackle this on my own, so I’m seeking your guidance, scripting dopers. I think this is a relatively simple script, but that just goes to show you how helpless I really am. Here’s what I need.

I get images delivered to me in folders, each folder having a name as follows

Node 0013
Node 2172
Node 1024
Node 0839
etc…

Note that the serial number for each node is always 4 digits long, with leading 0’s if necessary

Within each folder are **several **jpeg images with long complicated names that I change and move, but I only do this to the **last **image in each Node folder, the other images are just completely ignored (only one picture per folder is renamed and moved, and it’s always the last picture in the Node folder).

If you read my last thread, I change them to something like 18003222_dep.jpg, based on a value called Rec_ID that is captioned in each image. Well, with free OCR as unreliable as it is, I couldn’t get a script working to reliably read these values. However, I’ve come up with another solution! Each Node value matches up with a corresponding Rec_ID value, which I have in tab delimited ‘rec_id.txt’ file that I’ve been able to obtain that looks like this:

Serial Rec_ID
0013 18003222
1024 18003244
etc…

So, what I need to do is set up a script to run from the folder where all the Node directories are that will do essentially the following:

1)Get the serial value from a ‘Node ####’ folder (get rid of the Node part and keep just the ####, store as a variable SERIAL I guess)

2)search the ‘rec_id.txt’ file for the matching serial number (go line by line, store each serial value as a temporary variable, check to see if SERIAL = TEMP_SERIAL, if so then do the following

  1. store REC_ID value as a variable

4)Copy ONLY the last .jpg file (when sorted by date or by name, either works for these images) in the ‘Node SERIAL’ directory to a new file called REC_ID +"_dep.jpg"

  1. Move the REC_ID_dep.jpg image up one level to where the batch script will be running from. (this can probably just be done in step 4 actually)

  2. repeat for the next Node #### folder, until all the folders have been searched.

The final result should be that I have 1 jpeg from each Node #### folder now sitting in the directory where the script ran from, with the proper name.

A windows batch script would be ideal, but a linux bash script solution would also work if that’s your specialty.

Thank you so much in advance for any and all assistance. Even if all you have are resources for me to look stuff up, or hints, or whatever, I’d greatly appreciate it. I know I’m going to have to use some FOR loops but I’m not sure exactly what arguments/commands to pass them and how to parse what I need to parse. I also have no idea how to get values from a text file like I need to do.

I know just enough bash to be dangerous, but I’m far more comfortable in Python, so I went ahead and scribbled this down for you:



#!/usr/bin/env python
import os
import re
import shutil

# Read rec_ids.txt and build a mapping from serials to rec_ids
rec_ids = { k: v.strip() for k,v in map(lambda s: s.split('	'), open('rec_ids.txt')) }

# Find all directories which match the "Node XXXX" pattern
node_dirs = filter(lambda s: os.path.isdir(s) and re.match('Node \\d\\d\\d\\d$', s), os.listdir('.'))

for d in node_dirs:
    # Get listing of .jpg files in the directory
    jpegs = [os.path.join(d,f) for f in os.listdir(d) if os.path.splitext(f)[1] == '.jpg']

    # Copy the last one to the current directory, named according to rec_id
    shutil.copy(sorted(jpegs)[-1], '%s_dep.jpg' % rec_ids[d.split()[1]])


It should do the trick, I think. And you should be able to run it on either Windows or Linux (or OSX for that matter) as long as you have Python 2.7 installed.

Downloading python now. I’m on a very slow internet connection so it’s going to take some time. Thanks a bunch!

Since I posted this, I’ve been working on a windows batch script and I’m almost done with it, though I doubt it will be nearly as efficient as your program.

I’ll give both a try and report back with results! Once I really started getting into various help documents, batch wasn’t so scary… but I still don’t have it working yet so we’ll see :smiley:

Once python finishes downloading in about an hour and I install it, I’ll report back with results. Thanks so much!!!

No problem! Lemme know if it doesn’t work, I did just kinda fling it together in ten minutes or so. :stuck_out_tongue:

Script seems to work great! And I happened to finish mine before python was downloaded, and it works too.

Guess which one is faster? :smiley:

It’s nice that I figured it out on my own but the speed of that python script is essentially instantaneous, whereas my batch script takes several seconds.

Thanks again!

Also, my script has a stupid limitation of not allowing a file path with spaces in it. Yours doesn’t, so that’s a bonus!

Alright, glad to hear it worked. :slight_smile:

In my experience, Windows batch scripting has always been an enormous pain. Limited facilities, awkward and uncomposable syntax, the works. Bash scripting is more powerful but still kludgy. Python, on the other hand, is a lovely, lovely thing.

Yes, 100% agreed on all accounts. I haven’t done any python programming since my high school days, unfortunately. The only bonus to doing windows batch scripting is if you are on a locked down computer and can’t install other options. Luckily my work computer is not locked down, so downloading python wasn’t an issue.

Just for your reference, here is what the script looks like that I wrote for windows (not sure this was the best way, and I didn’t bother to comment it at all (I know I’m terrible), but here’s what it looks like):

@echo off
setlocal enableextensions enabledelayedexpansion
dir /ad /b > temp.txt
FOR /F “tokens=1,2” %%i in (temp.txt) do (
set serial=%%j
set serial=!serial:~0,4!
set Folder=Node !serial!
set Folder_path=%~dp0"!Folder!"
dir !Folder_path! /b > temp2.txt
FOR /F “tokens=* delims= " %%A IN (temp2.txt) DO (SET NewestFile=%%A)
FOR /F “tokens=1,2” %%X IN (rec_id.txt) DO (
SET temp_serial=%%X
SET rec_id=%%Y
if !temp_serial!==!serial! copy %~dp0”!Folder!"!NewestFile! %~dp0!rec_id!_dep.jpg
)
)
del temp.txt
del temp2.txt

It’s not at all obvious what most of that is doing, hahaha. Unlike the python code, which makes tons of intuitive sense looking at it!

Batch has actually been deprecated for like… 15 years or so on Windows at this point. You’re supposed to be using VBScript, JScript or PowerShell for tasks like this, and Batch only exists for legacy purposes.

Anyway, yes, Batch sucks, yes Microsoft’s aware that it sucks, yes it was replaced over a decade ago. Just FYI.

Fair point; and in true Microsoft style they replaced it with something that sucked less. :wink:

Hey I’ve got another question to ask relating to this script.

Now, this script works very beautifully for what we call the “deployment” phase of pictures (that’s what the _dep is for), but the “retrieval” phase will be a bit trickier to do by script because of the fact that the last picture in the directory is not the one we need. Unfortunately, it’s not the first picture either. It’s usually one of the middle pictures. Is it possible to modify this python script a little bit so that it counts up the number of pictures in the Node folder, and then takes and renames the middle picture? Or, and this might be asking for too much I realize, but would it be possible to bring up a window that displays little icons of all the pictures in a folder and lets the user click one to rename and move?

Or any other solutions you might come up with.

The problem of course is that for retrieval, even the middle-most picture might not be the right image to choose, so the process just can’t be quite as automated. But even a script that went and grabbed the middle image would automate maybe 70-80% of if. Letting the user see a screen of images and then clicking the one they want for the program to operate on would be the “best” solution but I realize that requires some GUI programming and I wouldn’t even know where to start with that.

The number of images in these folders is usually around 16, never more than 20, so even medium-size thumbnails could be displayed on the entire screen at one time and then chosen. Anyhow, I realize that’s a lot so even if we just modified the script to grab the middle image in the list would be great.

Thanks again!

Also, I am sorry I did a batch script when even Microsoft doesn’t want us writing them any more! I didn’t know about those other options. Are they included with Windows automatically? (That’s the only reason I tried batch)

Well, I managed to whip up a modified version of the script that pulls the middle file and renames it. That should work fairly well. Maybe in the future I’ll get into python gui programming and try my hand at creating selectable icons for it.

Microsoft’s problem is that even if they “deprecate” something, they leave it in there. For better or worse, when Apple deprecates something, they actually remove it.

But that’s the exact meaning of the word “deprecate” - to mark it as being superseded, rather than to remove it.

(bolding mine), from Deprecation - Wikipedia

I think removing something is worse, because it breaks compatibility - a deprecated feature can continue to be used, allowing an easier transition to using the new feature, or, if you so choose, being old-fashioned and not changing anything. I’m aware that maintaining endless backward compatibility is a pain in the neck for both users and developers, and contributes to older, badly-written applications living on endlessly, but I think that, at least in this case, the positives outweigh the pain of having to recode a lot of scripts that Just Work.

With these new requirements, you’re going to need a new tool. Unfortunately, this also means a new programming language/environment.

Since you’re running Windows, I’d recommend downloading a free copy of Visual Studio Express, which includes an easy visual window layout system called WinForms. (Which is more than powerful enough for your needs.) Using WinForms, you can just drag a grid of (say) 9 “PictureBox” objects onto a window and assign a Click action to each one to make the selection.

You can write the logic of the program either in C# or Visual Basic.net. The code is a little more involved, but the .net API is really comprehensive and powerful, so it’s all easily do-able without moving outside of the ecosystem.