Welcome guest. Before posting on our computer help forum, you must register. Click here it's easy and free.

Author Topic: Batch Files, Select all files EXCEPT  (Read 26220 times)

0 Members and 1 Guest are viewing this topic.

Salmon Trout

  • Guest
Re: Batch Files, Select all files EXCEPT
« Reply #15 on: May 17, 2011, 10:25:43 AM »
@Salmon Trout

I've never used tilde functions in batch scripting before.  I've found the MSDN site that has some information but I'm still not comprehending it.  Do you know of any good reference sites that have examples and explanations of usage?

The variable modifiers using the ~ symbol work like this:

In a batch, you can apply them to:

(1) the single % sign variables %0 to %9

%0 is the batch file itself
%1 to %9 are parameters passed into the batch file script the command line or from another script or program - if you type the line

mybatch.bat cat dog

at the prompt or include it in another script, then when mybatch.bat is running, it would expand %1 to be cat and %2 to be dog.

(2) The FOR metavariables %%A to %%Z and %%a to %%z.

below, the letter represents 0 to 9 or A-Z a-z

They work if the variable expands to a valid filename (which does not have to exist).

So if you do

for %%A in (*.*) do (

bla bla

)

In a loop, for each file found, in turn, %%~dA holds the drive letter (and colon), %%~pA the path (folder) name, %%~nA the name, %%~xA the extension (if any, with preceding dot). With passed parameters, if the parameter is a file name, then %~d1, %~p1, etc.

The drive, path, name, extension would work with a non-existent file, but you would get a null value for attributes, size in bytes or date for example.


    %~I         - expands %I removing any surrounding quotes (")
    %~fI        - expands %I to a fully qualified path name
    %~dI        - expands %I to a drive letter only
    %~pI        - expands %I to a path only
    %~nI        - expands %I to a file name only
    %~xI        - expands %I to a file extension only
    %~sI        - expanded path contains short names only
    %~aI        - expands %I to file attributes of file
    %~tI        - expands %I to date/time of file
    %~zI        - expands %I to size of file
    %~$PATH:I   - searches the directories listed in the PATH
                   environment variable and expands %I to the
                   fully qualified name of the first one found.
                   If the environment variable name is not
                   defined or the file is not found by the
                   search, then this modifier expands to the
                   empty string

The modifiers can be combined to get compound results:

    %~dpI       - expands %I to a drive letter and path only
    %~nxI       - expands %I to a file name and extension only
    %~fsI       - expands %I to a full path name with short names only
    %~dp$PATH:I - searches the directories listed in the PATH
                   environment variable for %I and expands to the
                   drive letter and path of the first one found.
    %~ftzaI     - expands %I to a DIR like output line



A good reference site is SS64.com

http://ss64.com/nt/

or the built-in command help (type the command followed by a space and a question mark e.g. FOR /?)


mechaflash

    Topic Starter


    Rookie
    • Yes
  • Experience: Experienced
  • OS: Windows XP
Re: Batch Files, Select all files EXCEPT
« Reply #16 on: May 17, 2011, 03:54:06 PM »
I want to say thank you mr. Salmon Trout.

I played around with the usage and your mysterious @ symbol to include the if with for statement and I have a nice small program that does what I need it to do.

Code: [Select]
@echo off
REM move to the right location
CD c:\test\

REM must be on to enumerate correctly
setlocal enabledelayedexpansion

REM set the counters and enumerate 'count' to the number of files
set /a number=0
set /a count=0
for %%F in (c:\test\*.*) do @if not "%%~xF"==".pdf" set /a count=!count!+1

REM decrease 'count' by 1 for every file, increase 'number' by 1 for every file,
REM set variables for attachments and include drive, path, filename, extension and a comma
REM after the extension.  Will skip last file as well.
for %%F in (c:\test\*.*) do @if not "%%~xF"==".pdf" @if /I !count! GTR 1 set /a count=!count!-1  & set /a number=!number!+1 & set file!number!=%%~dpnxF,
set /a count=0
offlocal

REM sets variable 'last' to the last file name without a comma
for %%F in (c:\test\*.*) do @if not "%%~xF"==".pdf" set last=%%F

REM Compose email with attachments
"c:\Program Files\Mozilla Thunderbird\thunderbird.exe" -compose "to='[email protected]',subject='Non-PDF File',preselectid='id',body='Please ensure that the entity is sending us a PDF file and not any other file type.  Attached is the file in question.',attachment='%file1%%file2%%file3%%file4%%file5%%file6%%file7%%file8%%file9%%file10%%last%'"


Sure the end is a little shabby with the 10 instances of the variables =D  but it works.  If anyone has maybe an easier way to accomplish this I'm all ears. 

Salmon Trout

  • Guest
Re: Batch Files, Select all files EXCEPT
« Reply #17 on: May 17, 2011, 04:23:43 PM »
You only need the @ before that IF at the command line. In a script, the @echo off at the beginning will have the same effect.

Here's how I would do this

Code: [Select]
@echo off
REM move to the right location
CD c:\test\

REM must be on to enumerate correctly
setlocal enabledelayedexpansion

REM Create string, set it to zero length
set AttachmentList=

REM Examine each file, if it is not a pdf, add its name to the list followed by a comma
for %%F in (c:\test\*.*) do if not "%%~xF"==".pdf" set AttachmentList=!AttachmentList!%%~dpnxF,

REM Remove final character (a comma)
set AttachmentList=%AttachmentList:~0,-1%

REM Compose email with attachments
"c:\Program Files\Mozilla Thunderbird\thunderbird.exe" -compose "to='[email protected]',subject='Non-PDF File',preselectid='id',body='Please ensure that the entity is sending us a PDF file and not any other file type. Attached is the file in question.',attachment='%Attachmentlist%'"



mechaflash

    Topic Starter


    Rookie
    • Yes
  • Experience: Experienced
  • OS: Windows XP
Re: Batch Files, Select all files EXCEPT
« Reply #18 on: May 18, 2011, 07:27:59 AM »
Code: [Select]
To ensure I'm understanding...

[quote author=Salmon Trout link=topic=119374.msg790530#msg790530 date=1305671023]
REM Remove final character (a comma)
set AttachmentList=%AttachmentList:~0,-1%
[/quote]

%AttachmentList:~0,-1%    is saying don't skip any characters from beginning of variable and do not read last 1 character of variable?

I keep trying to look up arguments like that and I can't find them for the life of me =/

What is that called when you use MyVar:~0,-1  and the like so I can study how it works?  To me, these are like the little hidden gems of batch scripts
« Last Edit: May 18, 2011, 08:17:37 AM by mechaflash »

Salmon Trout

  • Guest
Re: Batch Files, Select all files EXCEPT
« Reply #19 on: May 18, 2011, 10:41:46 AM »
Quote
What is that called when you use MyVar:~0,-1 and the like so I can study how it works?

It's called (among other things) "string slicing" or "extracting substrings".

Quote
%AttachmentList:~0,-1%    is saying don't skip any characters from beginning of variable and do not read last 1 character of variable?

The full syntax for specifying a substring (in this example %string% is the full string) is like this:

%string:~A,B%

A is the first character to take - it is the offset from the start, counting from 0 (not 1, notice).

B specifies the length. if B is a positive number, it means the number of characters to take. If B is a negative number, it means take up to the character which is B characters from the end, so if B is -1 it means take characters up to the last but one.

So if %string% is abcde then

%string:~0,2% is ab
%string:~2,2% is cd
%string:~0,-1% is abcd

There is a variation of this syntax which is a little complicated. If you only specify one number e.g %string:~X%

Then:

If the number is positive, then take from the character whose zero-based offset is X up to the end of the string so

%string:~1% would be bcde

If the number is negative, take the last X characters from the string so

%string:~-2% would be de

From the SET documentation:

Code: [Select]
If the length is not specified, then it defaults to the
remainder of the variable value.  If either number (offset or length) is
negative, then the number used is the length of the environment variable
value added to the offset or length specified.

You can fool about with all this at the prompt

Code: [Select]
c:\>set string=abcde

c:\>echo %string:~0,2%
ab

c:\>echo %string:~2,2%
cd

c:\>echo %string:~0,-1%
abcd

c:\>echo %string:~1%
bcde

c:\>echo %string:~-2%
de

c:\>

also note when the first number (of two) is negative, you count back from the end (starting at 1)

Code: [Select]
c:\>echo %string:~-3,1%
c

c:\>echo %string:~-3,2%
cd

c:\>echo %string:~-1,1%
e

c:\>echo %string:~-2,2%
de

c:\>echo %string:~-2,1%
d

I think I have covered most of it above, you can experiment yourself to get the hang of it, you seem the type! Unfortunately all too rare.

I am sure you will appreciate that a substring expression of the form %string:~A,B% is itself a variable and as such you can use it in various ways just like any other:

(This is not an exhaustive list!)

Echo directly to the console or a file

echo %string:~0,2%
echo The first two characters of %string% are %string:~0,2% > textfile.txt

Assign the substring to another string

set newstring=%string:~-4,2%

Test in an IF statement

IF "%string:~-4,2%"=="bc" bla bla bla

Convert the main string into a substring of itself

set string=%string:~-4,2%

... and so on

Quote
I keep trying to look up arguments like that and I can't find them for the life of me =/

There is quite a good explanation in the help for SET which you can access by typing SET /? in a console window. Otherwise, search the web.

A really good source of information and (often) illumination is the Usenet group alt.msdos.batch.nt, which is available in Google Groups. It's searchable and you'd be amazed what you can pick up by using it intelligently.


« Last Edit: May 18, 2011, 11:00:31 AM by Salmon Trout »

mechaflash

    Topic Starter


    Rookie
    • Yes
  • Experience: Experienced
  • OS: Windows XP
Re: Batch Files, Select all files EXCEPT
« Reply #20 on: May 19, 2011, 09:53:43 AM »
Final Code:
Added a way to exit the script if there aren't any files to process, as well as variable cleanup.

Code: [Select]
@echo off
REM move to the right location
CD c:\test

REM must be on to enumerate correctly
setlocal enabledelayedexpansion

REM Create string, set it to zero length
set AttachmentList=

REM Set error-out counter
set /a error=-1

REM Examine each file, if it is not a pdf, add its name to the list followed by a comma
for %%F in (c:\test\*.*) do if not "%%~xF"==".pdf" (set AttachmentList=!AttachmentList!%%~dpnxF,) & (set /a error=!error!+1)

REM End script if no files are processed
IF %error% LSS 0 GOTO cleanup

REM Remove final character (a comma)
set AttachmentList=%AttachmentList:~0,-1%

REM Compose email with attachments
"c:\Program Files\Mozilla Thunderbird\thunderbird.exe" -compose "to='[email protected]',subject='Non-PDF File',preselectid='id',body='Please ensure that the entity is sending us a PDF file and not any other file type. Attached is the file in question.',attachment='%Attachmentlist%'"

REM Run script to send email
START /WAIT c:\test\sendkeys.vbs

REM Move files to finished folder
for %%F in (c:\test\*.*) do if not "%%~xF"==".pdf" (move "%%~fF" "c:\test\finish\%%~nxF")
GOTO CLEANUP

:CLEANUP
set AttachmentList=
set /a error=0
localoff
GOTO NEXT

:NEXT
START c:\test\mainprogram.vbs

After this code runs, I run a simple .vbs for sendkeys to send the email automatically (no way to auto-send in thunderbird).  Then voila, no more looking in the directory to ensure we haven't received something other than a .PDF file. 

Purpose of creating this extra script:
I have an auto-print program that I created for my company that works in conjunction w/Thunderbird.  Thunderbird automatically pulls the attachments from all emails at a specified time.  Then all of the extracted PDFs are printed to a network printer for processing.  Then another script runs to check for the date of the file and delete any files older than 30 days.  Used daily and processes approximately 1200 documents a month.  The only problem I was having is receiving files that weren't PDF files, and they sometimes were unrelated to the task, but important to process none-the-less.  We did not want them mixed in with the rest of the files, but it still needed to be brought to the attention of the correct staff member.  So this is it...

TANXSOOMUCH SALMON!
« Last Edit: May 19, 2011, 10:12:26 AM by mechaflash »

Salmon Trout

  • Guest
Re: Batch Files, Select all files EXCEPT
« Reply #21 on: May 19, 2011, 10:27:35 AM »
You can remove the GOTO CLEANUP and GOTO NEXT lines in blue below - the code is gong to go to those labels anyway so they are superfluous.

REM Move files to finished folder
for %%F in (c:\test\*.*) do if not "%%~xF"==".pdf" (move "%%~fF" "c:\test\finish\%%~nxF")
GOTO CLEANUP

:CLEANUP
set AttachmentList=
set /a error=0
localoff
GOTO NEXT

:NEXT
START c:\test\mainprogram.vbs