Sunday, February 26, 2012

PowerShell: Moving Files Based On File Extension

I wrote this Saturday night. I had to recover all files on my storage server back in December/January, but I still haven't stored through them yet. All of the files are unsorted in the \testdisk-6.13\ folder, and need to be moved to individual folders for each file type for easier sorting (the \-=RECOVERED_FILES=-\JPEG\ folder, \PDF\, \AVI\, etc). Pretty self explanatory script.

#  Define file paths:
$Path = "C:\Users\Ken\Desktop\testdisk-6.13.win\testdisk-6.13\"
$Dest = "C:\Users\Ken\Desktop\-=RECOVERED_FILES=-\JPEG\"

#  Counter
$fNum = 0

#  Start-Transcript records everything up until Stop-Transcript is used (saved to log)
Start-Transcript C:\jpeg_transcript.txt

# If folder defined in $Path exists, get a list of all children (files/folders) and move each one to the $Dest folder
if(Test-Path $Path)
{
    try
    {
        Get-ChildItem -Path $Path -Recurse -Include *.JPEG | Move-Item -Destination $Dest -Force
        "    "
    }
    catch
    {
        #  Too lazy to do any error handling here...
        #  mainly because there are no duplicate file names...
        #  and if there are dupes, they'll be overwritten by -force.
        #  Also, any problematic files will be in the original folder, 
        #  so I can deal with them manually.
        "*** *** Couldn't do a damned thing! *** ***"
        "    "
    }
}
"Files moved: " + $fNum
"Files renamed: " + $fNum
Stop-Transcript

Thursday, February 2, 2012

8086 Assembler: Display the Month/Day/Year.

I wrote this program for my 80806 Assembler language class. I had problems at first realizing what each register in memory did, and how they correlated to each other. For example, the AX register is Word-sized, and contains two Byte-sized register: AH and AL (AH being the High byte, AL being the low byte). The same goes for DX (DH/DL), BX (BH/BL), CX (CH/CL). One thing I like about Assembler is how the interrupts for the operating system work.

For instance, to get the date from the OS, you first move the system code "2AH" into the "AH" register. After calling "INT 21H", the program will go to DOS and request the date, which is stored in the AH register. At that point, I can get the year (CX), month (DH, and day (DL).

What makes the program so long, though, is that in order for it to work, I need to PUSH the month/day/year to the stack individually - and the stack only accepts Word-sized data - yet in order to parse the numbers I need to do division on Byte-sized versions of the data (so if today is the 23rd, I'll need to divide 23 by 10, which stores the 2 in one register, and 3 in another register).

It's all very convoluted, but I figured I would post it to my blog anyway, so later I can come back and realize how much of a scrub I was at programming in Assembler ;-)

;Today.asm Display month/day/year.
;   Feb 1st, 2012
;CIS 206  Ken Howard

        .MODEL small

        .STACK 100h

        .DATA

        mess1 DB  10, 13, 'Today is $'  ; 10=LF, 13=CR

        .CODE

Today PROC

        MOV AX, @data            
        MOV DS, AX              

        MOV DX, OFFSET mess1    ; Move string to DX
        MOV AH, 09h             ; 09h call to display string (DX > AH > DOS)
        INT 21H                 ; Send to DOS        

                                ; CX year, DH month, DL day
        MOV AH, 2AH             ; Get the date (appendix D)
        INT 21H                 ; Send to DOS

        PUSH CX                 ; Move year to the stack
        MOV CX, 0               ; Clear CX

 MOV CL, DL
        PUSH CX                 ; Move day to stack

        MOV CL, DH              ; Move month > CL
        PUSH CX                 ; Move month to stack

 MOV DH, 0               ; Clear DH         

 ; ************************** DISPLAY MONTH ************************ 
        ; Set up for division
                                ; Dividend will be in DX/AX pair (4 bytes)
                                ; Quotient will be in AX
                                ; Remainder will be in DX

        MOV DX, 0               ; Clear DX
        POP AX                  ; Remove month from stack into AX


        MOV CX, 0               ; Initialize the counter
        MOV BX, 10              ; Set up the divisor

dividem:                         

        DIV BX                  ; Divide (will be word sized)
        PUSH DX                 ; Save remainder to stack

        ADD CX, 1               ; Add one to counter
        MOV DX, 0               ; Clear the remainder
        CMP AX, 0               ; Compare quotient to zero
        JNE dividem             ; If quoient is not zero, go to "dividem:"

divdispm:

        POP DX                  ; Remove top of stack into DX
           
        ADD DL, 30h             ; ADD 30h (2) to DL 
        MOV AH, 02h             ; 02h to display AH (DL)
        INT 21H                 ; Send to DOS

        LOOP divdispm           ; If more to do, divdispm again
                                ; LOOP subtracts 1 from CX. If non-zero, loop.

        MOV DL, '/'             ; Character to display goes in DL
        MOV AH, 02h             ; 02h to display AH (DL)
        INT 21H                 ; Send to DOS



 ; ************************** DISPLAY DAY ************************
        ; Set up for division
                                ; Dividend will be in DX/AX pair (4 bytes)
                                ; Quotient will be in AX
                                ; Remainder will be in DX



        MOV DX, 0               ; Clear DX
        POP AX                  ; Remove day from stack into AX


        MOV CX, 0               ; Initialize the counter
        MOV BX, 10              ; Set up the divisor

divided:                         

        DIV BX                  ; Divide (will be word sized)
        PUSH DX                 ; Save remainder to stack

        ADD CX, 1               ; Add one to counter
        MOV DX, 0               ; Clear the remainder
        CMP AX, 0               ; Compare quotient to zero
        JNE divided              ; If quoient is not zero, go to "divided:"

divdispd:

        POP DX                  ; Remove top of stack
           
        ADD DL, 30h             ; ADD 30h (2) to DL 
        MOV AH, 02h             ; 02h to display AH (DL)
        INT 21H                 ; Send to DOS

        LOOP divdispd           ; If more to do, divdispd again
                                ; LOOP subtracts 1 from CX. If non-zero, loop.
       

        MOV DL, '/'             ; Character to display goes in DL
        MOV AH, 02h             ; 02h to display AH (DL)
        INT 21H                 ; Send to DOS
        


 ; ************************** DISPLAY YEAR ************************
 ; Set up for division
                                ; Dividend will be in DX/AX pair (4 bytes)
                                ; Quotient will be in AX
                                ; Remainder will be in DX

        MOV DX, 0               ; Clear DX
        POP AX                  ; Remove month from stack into AX


        MOV CX, 0               ; Initialize the counter
        MOV BX, 10              ; Set up the divisor

dividey:                         

        DIV BX                  ; Divide (will be word sized)
        PUSH DX                 ; Save remainder to stack

        ADD CX, 1               ; Add one to counter
        MOV DX, 0               ; Clear the remainder
        CMP AX, 0               ; Compare quotient to zero
        JNE dividey             ; If quoient is not zero, go to "dividey:"

divdispy:

        POP DX                  ; Remove top of stack into DX
           
        ADD DL, 30h             ; ADD 30h (2) to DL 
        MOV AH, 02h             ; 02h to display AH (DL)
        INT 21H                 ; Send to DOS

        LOOP divdispy           ; If more to do, divdisp again
                                ; LOOP subtracts 1 from CX. If non-zero, loop.

        MOV al, 0               ; Use 0 as return code
        MOV AH, 4ch             ; Send return code to AH
        INT 21H                 ; Send return code to DOS to exit.

Today   ENDP                    ; End procedure
END     Today                   ; End code. Start using "Today" procedure.