1. Computer problem? Tech Support Guy is completely free -- paid for by advertisers and donations. Click here to join today! If you're new to Tech Support Guy, we highly recommend that you visit our Guide for New Members.

Is this possible with Batch Scripting?

Discussion in 'Software Development' started by bassmadrigal, Apr 13, 2010.

Thread Status:
Not open for further replies.
Advertisement
  1. bassmadrigal

    bassmadrigal Thread Starter

    Joined:
    Dec 16, 2009
    Messages:
    65
    I am wanting to create a script to help simplify my life at work. Everyday we have to take between 15-50 pdf files and sort them into folders based off their filename. The filename is 12-13 characters long. The standard format is ABCABCABC123.pdf. Basically, I could care less about the first 9 characters of the filename. The key is the last 3-4 characters. They will be the ordinal date (the number of days from January 1st) with the possiblility of an 'a' after it (ie ABCABCABC123a.pdf). I want to somehow extract the number (ie ordinal date) from the filename so I can move it into a particular folder. The 'a' means it needs to go into a different folder structure altoghether.

    Initially I thought this would be a fairly straightforward script after a bit of googling, but it has proven otherwise. I am still not used to the limited functionality of batch scripting vs bash shell scripting. It seems there is no windows equivalent for sed or cut (without installing software, which I don't have access to do on my works computer). Which seems to make what I want to do impossible

    I am not wanting someone to create a script for me (I would rather learn the code myself), but I am wondering if it is even possible? I don't want to spend a ton of time trying to figure out how to do things, just to find out it is impossible. If it is possible, could you post the commands that I can use and maybe a possible resource to read up on it?

    Thanks
    Jeremy
     
  2. Squashman

    Squashman Trusted Advisor

    Joined:
    Apr 4, 2003
    Messages:
    19,786
    I believe it can be done. I was a bash shell scripting guy myself many years ago and it took me a while to figure out. If you have never done batch you might as well just start learning PowerShell instead. It is Microsoft's replacement for the cmd prompt and batch. It has a ton of more options

    While it is true that there is no direct one to one relationship to SED and CUT in batch, it does come close. You can't really do regular expression replacing like SED can but you can do string replacement (SED) and substrings(CUT) wit the SET statement.

    So to cut something from a variable.
    Code:
    H:\>set _Temp1=0123456789
    
    H:\>set _Temp2=%_Temp1:~0,5%
    
    H:\>echo %_Temp2%
    01234
    
    H:\>
    And you can do string replacement similar to sed but you can't use regular expressions

    Code:
    H:\>set _Temp3=%_Temp1:0=1%
    
    H:\>echo %_Temp3%
    1123456789
    
    H:\>
     
  3. bassmadrigal

    bassmadrigal Thread Starter

    Joined:
    Dec 16, 2009
    Messages:
    65
    Awesome. That is giving me some great footing to start on. I was thinking that the code you used in the examples below was only for space delimited strings (looking back, I am not sure why I came up with that idea).

    As far as using powershell, I remember reading about that back when Vista was still considered Longhorn and they were going to implement it. Unfortunately though, the systems I use at work will not allow me to install software. I am limited to batch scripting.

    And I normally don't do any batch scripting except for this and one other script at work. At home, I am running Slackware, so I can use bash.

    One other quick question. Do you know of any easy way to count the number of characters in a string (ie, count the length of the filename)? There are ways around it if I can't count that, but it would simplify things with a couple of if/else statements.

    Thanks again!!
    Jeremy
     
  4. Squashman

    Squashman Trusted Advisor

    Joined:
    Apr 4, 2003
    Messages:
    19,786
    Why do you need to know the length. If the numbers are the last part of the filename you can just pull the last 3 or 4 characters of the filename.
    Code:
    H:\>set _Temp4=%_Temp1:~-4,4%
    
    H:\>echo %_Temp4%
    6789
     
  5. Squashman

    Squashman Trusted Advisor

    Joined:
    Apr 4, 2003
    Messages:
    19,786
  6. Squashman

    Squashman Trusted Advisor

    Joined:
    Apr 4, 2003
    Messages:
    19,786
    The second example in that link works just fine and is probably easier to understand. I think it will run faster as well because we are using smaller strings. If you were using variables that were a couple hundred characters in length then the divide and conquer method would probably be better.

    I don't necessarily like his use of single character variable names. It can get confusing because For Loops use single characters for their variables in batch files.
     
  7. TheOutcaste

    TheOutcaste

    Joined:
    Aug 7, 2007
    Messages:
    9,028
    I'm assuming the ordinal date is 001-366. Remember that numbers starting with a zero are treated as base 8, so you can get some strange results when comparing numbers, or get errors if trying to do math with them.
    What I would do is check the last character of the filename. you don't need to know the length to do this. If not a number, then the a is present.
    Then extract and convert the date to a useable number that won't be seen as octal. Again, you don't need to know the length to do this:
    Set _Filedate=%_FileName:~-4,-1% will extract the 3 digit date and discard the ending a.
    My first thought is to extract and convert the dates like this:
    Dates without the a will be 1001-1366
    Dates with the a will be 10010-13660
    all done in one If Else statement, easy to tell apart, and easy to convert back to the date.

    Or you can set a flag to show whether or not the a is present.

    If you really want to get the length of a string, theres the two routines Squashman linked.

    You can just count the characters. Slow for long strings
    The divide by two is faster for strings longer than 16 characters.
    Here's a 3rd method that I think is fastest for strings less than 150 characters or so:
    Code:
    :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    :_GetLength
    :: Gets the length of a passed variable
    :: Arguments : "string" rvar
    :: Returns   : Length of string in specified return var
    :: Usage
    :: Call :_GetLength "%str%" rvar
    ::    "%str%"    : String to find length of. Must be quoted if contains spaces
    ::    rvar        : Name of variable to be used to return the length
    :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    SetLocal
    Set _Len=0
    Set _Str=%~1
    If Not Defined _Str Goto :EOF
    Set _Str=%_Str:"=.%987654321
    :_Loop
    If Not "%_Str:~18%"=="" Set _Str=%_Str:~9%& Set /A _Len+=9& Goto _Loop
    Set _Num=%_Str:~9,1%
    Set /A _Len=_Len+_Num
    EndLocal&Set %2=%_Len%&Goto :EOF
    
     
  8. bassmadrigal

    bassmadrigal Thread Starter

    Joined:
    Dec 16, 2009
    Messages:
    65
    Basically I was going to use the string length to determine if it had the 'a' at the end.

    How we are currently doing this, is we sort each file based on the ordinal date (I needed the string extracted so I could move it into the proper folder). Then if it was 13 characters (well technically 17 with the period and the extension) it would put it into the LTF directories. I was originally thinking of just doing a simple if $char = 13 then move it to ltf elseif $char = 12 then move it to stf else do nothing (there will be files in there that do not match up to either naming convention).

    Code:
    FY10
    ->STF
      ->001
        ->ABCABCABC001
          ->ABCABCABC001.pdf
        ->ABCABCABB001
        ->ABCABCAAA001
      ->002
      ->003
    ->LTF
      ->001
        ->ABCABCABC001a
          ->ABCABCABC001a.pdf
        ->ABCABCABB001a
        ->ABCABCAAA001a
      ->002
      ->003
    So I may have to pad the variable with zeros, depending on how they are interpreted (trial and error when I get back to work), but it shouldn't be too difficult. But there won't be any math done on them, so I am hoping it keeps it as char. I suppose to determine if the 'a' is present, I can just extract the 13th character and check to see if it is an 'a' (those will be the longest filenames in the directory). Otherwise if it is a period, I move it to the STF folder. And if it is anything else, it just stays in the directory.

    I appreciate all the feedback, and I am looking forward to digging back into this at work tomorrow.
    Jeremy
     
  9. Rollin_Again

    Rollin_Again

    Joined:
    Sep 4, 2003
    Messages:
    4,912
    This can also be done using Visual Basic scripting. Let me know if you want to go this route.

    Rollin
     
  10. bassmadrigal

    bassmadrigal Thread Starter

    Joined:
    Dec 16, 2009
    Messages:
    65
    I don't have administrator rights on the computer to install visual basic (if it is even needed). But I am fairly unfamiliar with this language, and it may be able to be programmed directly in the cmd window. I just don't know.

    OK, so I got quite a bit taken care of today while at work. I had a few hiccups, like figuring out that variables within a for statement need '!' around them rather than '%' (still not sure why, but oh well).

    But I am stumped on one thing. There is a possibility of multiple files having the same name (obviously not in the directory that I am starting from), so I am trying to figure out how to have it check if the file exists already and then have it change the name so it can store it properly. Ideally I would use a while loop, but they don't exist in batch programming, so I figured I could do it with some simple labels and goto statements with an if statement. However, it isn't working like I had hoped.

    My makeshift while loop works properly, but after it exits, it decides to leave the whole for loop. Here is the full script:

    Code:
    @echo off
    SETLOCAL EnableDelayedExpansion
    set _filename=
    set _ord=
    for %%f in (*.pdf) do (
     set _filename=%%f
     set _ord=!_filename:~9,3!
     set _ltf=!_filename:~12,1!
     set _folder=!_filename:~0,12!
     set _extra=
     if !_ltf! == a (
      if NOT EXIST LTF\!_ord!\!_folder!\ (
       md LTF\!_ord!\!_folder!\
      )
      set _count=0
      :WhileLTF
      if exist LTF\!_ord!\!_folder!\!_folder!!_extra!.pdf (
       set /a count = !count! + 1
       set _extra=-!count!
       echo !count!
       goto WhileLTF
      )
      copy !_filename! LTF\!_ord!\!_folder!\!_folder!!extra!.pdf
     ) else (
     if !_ltf! == . (
      if NOT EXIST STF\!_ord!\!_folder!\ (
       md STF\!_ord!\!_folder!\
      )
      set _count=0
      :WhileSTF
      if exist STF\!_ord!\!_folder!\!_folder!!_extra!.pdf (
       set /a count = !count! + 1
       set _extra=-!count!
       echo !count!
       goto WhileSTF
      )
       copy !_filename! STF\!_ord!\!_folder!\!_folder!.pdf
     )
     )
    )
    
    Hopefully this makes some sense. I can't figure out why this is happening, and I haven't had much luck searching google (although I may not know the proper search terms). I am really close to this, and I just can't figure out why it doesn't work.

    As always, any help would be greatly appreciated.
    Jeremy
     
  11. Squashman

    Squashman Trusted Advisor

    Joined:
    Apr 4, 2003
    Messages:
    19,786
    VBscript not VB. Doesn't need anything installed.
     
  12. Squashman

    Squashman Trusted Advisor

    Joined:
    Apr 4, 2003
    Messages:
    19,786
    Use the CALL command instead of GOTO. Goto breaks out of the loop. CALL will jump to a label or another batch file and return to the same spot it left off.
     
  13. Squashman

    Squashman Trusted Advisor

    Joined:
    Apr 4, 2003
    Messages:
    19,786
    I should elaborate on that. Any functions that work independent of main program should be moved outside of the for loop. Move all your functions (ie labels) to the bottom of your batch file and outside of the For Loop.

    Also...
    You are declaring the variable _count but incrementing the variable count. You should also use different variables for your counting for the LTF and STF.
     
  14. Squashman

    Squashman Trusted Advisor

    Joined:
    Apr 4, 2003
    Messages:
    19,786
    In your example above you are using the "a" at the end of the file name as part of the folder name. Your batch file is not using the "a" in the folder name.

    If you set a variable to equal STF or LTF based on the 13 position being an "a" or "." you could shorten up your batch file by alot!!! You wouldn't need two separate if loops and gotos.

    Your second copy statement isn't using the EXTRA varaible for the copy.
     
  15. Squashman

    Squashman Trusted Advisor

    Joined:
    Apr 4, 2003
    Messages:
    19,786
    Well I am going to post my code first but I like what TheOutcaste is going to post after me. I have not tested this. All I did was condense and fix some of your code.
    Code:
    @echo off
    SETLOCAL EnableDelayedExpansion
    set _filename=
    set _ord=
    for /f "tokens=*" %%F in ('dir /a-d /b *.pdf') do (
    	set _filename=%%F
    	set _folder=%%~nF
    	set _ord=!_filename:~9,3!
    	set _ltf=!_filename:~12,1!
    	set _extra=
    	set _Dsub=
    	if !_ltf! == a set _Dsub=LTF
    	if !_ltf! == . set _Dsub=STF
    	If Not !_Dsub!=="" (
    		If NOT EXIST !_Dsub!\!_ord!\!_folder!\ md !_Dsub!\!_ord!\!_folder!\
    		Call :COPYFILE
    	)
    )
    goto :EOF
    
    :COPYFILE
    set _extra=
    set _count=0
    :Loop
      if exist !_Dsub!\!_ord!\!_folder!\!_folder!!_extra!.pdf (
       set /a _count+=1
       set _extra=-!_count!
       echo !_count!
       goto Loop
      )
    copy !_filename! !_Dsub!\!_ord!\!_folder!\!_folder!!extra!.pdf
     
  16. Sponsor

As Seen On
As Seen On...

Welcome to Tech Support Guy!

Are you looking for the solution to your computer problem? Join our site today to ask your question. This site is completely free -- paid for by advertisers and donations.

If you're not already familiar with forums, watch our Welcome Guide to get started.

Join over 733,556 other people just like you!

Loading...
Similar Threads - possible Batch Scripting
  1. alivtar
    Replies:
    0
    Views:
    509
Thread Status:
Not open for further replies.

Short URL to this thread: https://techguy.org/916576

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice