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 26217 times)

0 Members and 1 Guest are viewing this topic.

mechaflash

    Topic Starter


    Rookie
    • Yes
  • Experience: Experienced
  • OS: Windows XP
Batch Files, Select all files EXCEPT
« on: May 13, 2011, 11:57:38 AM »
I'm creating a batch script that will filter out files from a folder and move them elsewhere.

In my example, I have folder filled with .PDF files.  Every so often, a .TIFF or .DOC file etc. will get mixed into it, and I don't want them there.  How would I go about selecting all files EXCEPT .PDF files and move them to another folder?

Salmon Trout

  • Guest
Re: Batch Files, Select all files EXCEPT
« Reply #1 on: May 13, 2011, 12:42:32 PM »
How would I go about selecting all files EXCEPT .PDF files and move them to another folder?

You could use FOR /F to parse the output of DIR /B piped through FIND /V ".PDF".




mechaflash

    Topic Starter


    Rookie
    • Yes
  • Experience: Experienced
  • OS: Windows XP
Re: Batch Files, Select all files EXCEPT
« Reply #2 on: May 13, 2011, 01:01:32 PM »
You could use FOR /F to parse the output of DIR /B piped through FIND /V ".PDF".

Logic is wrong (if I'm not mistaken)

Your asking to call DIR for all files in directory, then find all .PDF files and assign them to variables.  I want to find files EXCEPT for .PDF files.  I don't want the .PDF files selected.

Either case I attempted to run the code and it returned "More?" indefinitely unless terminated.

I'm really not sure if this is possible   :(



Salmon Trout

  • Guest
Re: Batch Files, Select all files EXCEPT
« Reply #3 on: May 13, 2011, 01:05:33 PM »
You are mistaken. The logic is fine. The problem is you don't know that the /V switch makes FIND ignore all items containing the specified string. You could have found this by typing FIND /? at the prompt.

Another way is to use FOR to list all files in the directory, and in the loop, use the ~x variable modifier to isolate each file's extension and if it is not ".pdf", perform the move operation. (see FOR /? for details.)

Quote
I attempted to run the code

What code? I don't see any. You really should post the code you are running and state how you are trying to run it, if you want help that is more specific.

Quote
I'm creating a batch script

Why so shy about posting what you have done so far?


« Last Edit: May 13, 2011, 01:15:41 PM by Salmon Trout »

mechaflash

    Topic Starter


    Rookie
    • Yes
  • Experience: Experienced
  • OS: Windows XP
Re: Batch Files, Select all files EXCEPT
« Reply #4 on: May 13, 2011, 02:30:49 PM »
I apologize as the logic is correct.  overlooked the /v switch.  But it seems as though for /f doesn't like the command dir | find.  This is what I used to test. (directly in cmd not batch)

for /F %G IN (dir /s /a /b c:\test\ | find /v ".pdf") do "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='%G'"

it returns:
"| was unexpected at this time."

i tried doing ("dir /s /a /b c:\test\ | find /v '.pdf'")
                   ("dir /s /a /b c:\test\"|"find /v '.pdf'")
                   ('dir /s /a /b c:\test\'|'find /v ".pdf"')
                   ('dir /s /a /b c:\test\ | find /v ".pdf"')

all returning the same error.
it works fine if it's not a part of the FOR command however.

p.s. Yes I know it's not a move command  ::)
« Last Edit: May 13, 2011, 02:49:21 PM by mechaflash »

Geek-9pm


    Mastermind
  • Geek After Dark
  • Thanked: 1026
    • Gekk9pm bnlog
  • Certifications: List
  • Computer: Specs
  • Experience: Expert
  • OS: Windows 10
Re: Batch Files, Select all files EXCEPT
« Reply #5 on: May 13, 2011, 03:09:35 PM »
Pardon me.
Could one not just use the ATTRIB  command?

Code: [Select]
ATTRIB +H *.PDF
dir /b

mechaflash

    Topic Starter


    Rookie
    • Yes
  • Experience: Experienced
  • OS: Windows XP
Re: Batch Files, Select all files EXCEPT
« Reply #6 on: May 13, 2011, 03:30:39 PM »
jeez u make me work so hard... i created this and it works:
dir /s /b /a:-d c:\test\ > c:\TEMP\dir.txt
for /f  "tokens=*" %%G IN ('find /V /I ".pdf" c:\TEMP\dir.txt') do "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='%%G'"


but i think setting the attribute then doing dir will be easier. cause then I can set variables directly from dir instead of dir piped through find anyways.

Just have to remember to put attrib -h *.pdf towards the end of the function

mechaflash

    Topic Starter


    Rookie
    • Yes
  • Experience: Experienced
  • OS: Windows XP
Re: Batch Files, Select all files EXCEPT
« Reply #7 on: May 13, 2011, 03:33:35 PM »
confirmed works beautifully  ;D

Final Code

Code: [Select]
attrib +h *.pdf
for /f "tokens=*" %%G IN ('dir /s /b c:\test\') do "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='%%G'"
attrib -h *.pdf

mechaflash

    Topic Starter


    Rookie
    • Yes
  • Experience: Experienced
  • OS: Windows XP
Re: Batch Files, Select all files EXCEPT
« Reply #8 on: May 13, 2011, 03:42:13 PM »
now if I could just figure out a way to add a comma onto the end of the file names via this method when it gets inserted into the Thunderbird compose command... then I can send all of them via 1 email =D

Salmon Trout

  • Guest
Re: Batch Files, Select all files EXCEPT
« Reply #9 on: May 13, 2011, 04:04:08 PM »
"| was unexpected at this time."

You have to escape the pipe symbol with a caret thus: ^|


Salmon Trout

  • Guest
Re: Batch Files, Select all files EXCEPT
« Reply #10 on: May 13, 2011, 04:06:49 PM »
put attrib -h *.pdf towards the end of the function

This is a daft idea. I suspect geek has has some kind of cerebro-vascular accident, the way he has been posting lately. Or perhaps that is his default mode? Still, you are perfectly free to accept his kludgy workaround.

Salmon Trout

  • Guest
Re: Batch Files, Select all files EXCEPT
« Reply #11 on: May 13, 2011, 04:09:16 PM »
works beautifully  ;D

They say beauty is in the eye of the beholder  ::)

Salmon Trout

  • Guest
Re: Batch Files, Select all files EXCEPT
« Reply #12 on: May 14, 2011, 03:59:34 AM »
Another way is to use FOR to list all files in the directory, and in the loop, use the ~x variable modifier to isolate each file's extension and if it is not ".pdf", perform the move operation. (see FOR /? for details.)

Personally I prefer this approach; it targets the actual file extension rather than picking up every file which has the string ".pdf" somewhere in its name

Use one percent sign for the variable ("%A") at the prompt and two percent signs in a batch script ("%%A")

Code: [Select]
for %A in (*.*) do @if not "%~xA"==".pdf" echo Moving %A & move "%A" "C:\Path\Folder"

mechaflash

    Topic Starter


    Rookie
    • Yes
  • Experience: Experienced
  • OS: Windows XP
Re: Batch Files, Select all files EXCEPT
« Reply #13 on: May 16, 2011, 03:01:16 PM »
Total program thus far... (pain in the *censored* to get it to put the files the way I need it to for it to compose as attachments in a thunderbird email)

Code: [Select]
@echo off
SETLOCAL ENABLEDELAYEDEXPANSION

CD c:\test\

REM Hide all PDF files from commands
ATTRIB +H *.pdf

REM Output directory/names of files to c:\temp\dir.txt Alphabetically
DIR /S /B /O:N>c:\TEMP\dir.txt

CD c:\temp\

REM Read last line in file and output to file c:\temp\last.txt
FOR /F "tokens=*" %%F IN (dir.txt) DO echo %%F>c:\temp\last.txt

REM Count the lines in file
set /a count=-1
for /F %%a in (dir.txt) DO set /a count=!count!+1

REM Create empty temp file
copy /y NUL tempfile.txt >NUL

REM Copy all but last line
for /F %%F in (dir.txt) DO (
IF /I !count! GTR 0 (
echo %%F,>>tempfile.txt
set /a count=!count!-1
)
)

REM overwrite original file, delete temp file
copy /y tempfile.txt dir.txt >NUL
del tempfile.txt

REM output the last file back into dir.txt (without comma)
for /F %%F in (last.txt) DO echo %%F>>dir.txt


REM Compose email with attachments, loop once for all lines
set /a count=1
for /F "tokens=* delims=" %%F in (dir.txt) DO (
IF /I !count! GTR 0 (
"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='%%F'"
set /a count=!count!-1
)
)

REM Change back attributes
ATTRIB -H *.pdf

REM Cleanup
del attach.txt dir.txt last.txt
OFFLOCAL

Here's my problem... I need to have ALL of the files attach at the end of the compose command... but because it's a "for each" type of statement it will loop it for every file telling it to compose a new email.

I set it up to where there is a comma after each file except for the last one in the list so when it composes it will be file1,file2,file3,lastfile because Thunderbird needs it formatted in such a way.

How would I go about just reading all the lines in attach.txt and grabbing it as ONE string to insert?  Or is there a way to use FOR to grab all lines at once?

THANKS!
« Last Edit: May 16, 2011, 03:25:24 PM by mechaflash »

mechaflash

    Topic Starter


    Rookie
    • Yes
  • Experience: Experienced
  • OS: Windows XP
Re: Batch Files, Select all files EXCEPT
« Reply #14 on: May 17, 2011, 08:22:22 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?

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