Solved

Batch File: FOR /R Copy file with exclamation point in the name

Posted on 2010-08-30
13
1,246 Views
Last Modified: 2012-05-10
Hi there,

By using a FOR /R command as my provided script, I need to copy files that some times, will have an exclamation mark in the name.

I tried to add an escape code to it, [SET FileName=!FileName:^!=^!!] but I guess I was too ambitious here.

Thanks for your help,
Rene






@echo off

setlocal enabledelayedexpansion



SET SOURCE=C:\Batchfiles\TESTING\1

SET DESTIN=C:\Batchfiles\TESTING\2



for /R "%SOURCE%" %%A in (*.*) do (

	SET FileName=%%A

	ECHO COPYING !FileName!

	COPY /Y "!FileName!" "%DESTIN%"

	)

PAUSE

EXIT

Open in new window

0
Comment
Question by:ReneGe
  • 7
  • 6
13 Comments
 
LVL 51

Expert Comment

by:Bill Prew
ID: 33563413
Dealing with ! in strings like filenames in BAT files can be rather tricky.

In your original example it isn't possible, because the ! never actually gets into the FileName variable.  When the statement

SET FileName=%%A

executed, it replaces %%A with it's value, and then proceeds to parse the line.  It will see the ! point, and since you have enabled delayed expansion, it treats that as a special character and "eats it up",

For the example you provided, attached is a working solution.

~bp
@ECHO OFF
  
SET SOURCE=C:\Batchfiles\TESTING\1
SET DESTIN=C:\Batchfiles\TESTING\2
 
FOR /R "%SOURCE%" %%A IN (*.*) DO (
        ECHO COPYING %%A
        COPY /Y "%%A" "%DESTIN%"
        )
PAUSE
EXIT /B

Open in new window

0
 
LVL 51

Expert Comment

by:Bill Prew
ID: 33563423
For what it's worth, using special characters in Windows file names other than a couple of safe ones like dash, underscore, space can often lead to undesirable consequences in different applications.  I typically try and avoid things like slashes, colons, exclamations, percents, etc.

~bp
0
 
LVL 10

Author Comment

by:ReneGe
ID: 33563535
My challange here is that this script is part of a bigger script that delayed expansion must be enabled.

Let's say it must work with the following script.

Can then delayed expansion be turned off then on within the secong loop, or something?

Thanks,
Rene
@echo off

SETLOCAL enabledelayedexpansion



	SET SOURCE=C:\Batchfiles\TESTING\1

	SET DESTIN=C:\Batchfiles\TESTING\2



FOR /L %%A IN (1,1,2) DO (

	SET TIMES=%%A

	FOR /R "%SOURCE%" %%B IN (*.*) DO (

		SET FileName=%%B

		ECHO COPYING !TIMES! TIMES: %FileName%

		COPY /Y "%FileName%" "%DESTIN%"

	)

)



PAUSE

EXIT /B

Open in new window

0
 
LVL 51

Expert Comment

by:Bill Prew
ID: 33563550
Why not do it this way?

~bp
0
 
LVL 51

Accepted Solution

by:
Bill Prew earned 500 total points
ID: 33563554
Why not do it this way?

~bp
@echo off

        SET SOURCE=C:\Batchfiles\TESTING\1
        SET DESTIN=C:\Batchfiles\TESTING\2

FOR /L %%A IN (1,1,2) DO (
        FOR /R "%SOURCE%" %%B IN (*.*) DO (
                ECHO COPYING %%A TIMES: %%B
                COPY /Y "%%~B" "%DESTIN%"
        )
)

PAUSE
EXIT /B

Open in new window

0
 
LVL 10

Author Comment

by:ReneGe
ID: 33563579
That should do it!

Thanks bp  :~)

Cheers,
Rene
0
Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

 
LVL 51

Expert Comment

by:Bill Prew
ID: 33563585
Great, thanks.

~bp
0
 
LVL 10

Author Comment

by:ReneGe
ID: 33568709
Well finally, I'm still challanged with it.

I dont see how I can use the values contained in the variables "SET BasePath_Dest=!BasePath_Dest%%A!" without using delayed expansion enabled.

Would you mind giving it a look and give me your feedback?

Thanks,
Rene
@echo off



SETLOCAL enabledelayedexpansion



REM SETTING STATIC VARIABLES (TheDate=!Year!-!Month!-!Day!) (TheTime=!Hour!.!Min!.!Sec!)

	CALL :GetDateTime "Month" "Day" "Year"

	SET TimeStart=%date%  %time%





ECHO ^>READING INI FILES

REM for /F "tokens=1,2 delims=^=" %%A in (Settings.ini) do SET Setting.ini_%%A=%%B

	SET CounterPath=0

	for /F "tokens=1-4 delims=^>" %%A in (Paths.ini) do (

		SET /a CounterPath=!CounterPath! + 1

		SET BasePathName=%%A

		SET BasePath_Source!CounterPath!=%%B

		SET BasePath_Dest!CounterPath!=%%C

		SET BasePath_Archives!CounterPath!=%%D

	)







etc...





	

	FOR /L %%A in (1,1,%CounterPath%) do (

		ECHO  ------------------------------------------------------------

		REM SETUP BASE FOLDERS

			SET BasePath_Source=!BasePath_Source%%A!

			SET BasePath_Dest=!BasePath_Dest%%A!

			SET BasePath_Archives=!BasePath_Archives%%A!\%Year%\%Month%\%Day%-%Hour%h

			IF NOT EXIST "!BasePath_Archives!" MD "!BasePath_Archives!"

			IF NOT EXIST "!BasePath_Dest!" MD "!BasePath_Dest!"

			ECHO COUNTER=%%A  BasePath_Source=!BasePath_Source!  BasePath_Dest=!BasePath_Dest!  BasePath_Archives=!BasePath_Archives!

			FOR /F "TOKENS= 2 DELIMS=	" %%A IN ('Robocopy "!BasePath_Dest!" "!BasePath_Source!" * /E /MIR /L /NJH /NJS /NS /NDL /XF *.mp3 *.wav *.avi *.wma *.iso /XD ISO "Virtual Machines *" Musique test ^| Findstr -V ^*') DO (

				SET PathSource=%%~pA

				SET SourceSize=%%~zA

				SET FileFull=%%A

				SET ZipFile=!BasePath_Archives!%%~spnA.zip

				Echo %TheDate%^>%TheTime%^>!SourceSize!^>!FileFull!^>!ZipFile!>>"%File_Archives_Index%"

				ECHO.

				ECHO ARCHIVING: !FileFull!

				ECHO        TO: !ZipFile!

				"C:\Program Files\7-Zip\7z.exe" a -ppatoF645 -mx=9 "!ZipFile!" "!FileFull!">>"%File_LOG_Archives%_temp.TXT"

				SET Result=!errorlevel!

				IF !Result! NEQ 0 (

					ECHO !Result! ---^> "!FileFull!" >>%File_LOG_ArchivesError%

					ECHO ARCHIVE ERROR

				) ELSE (

					ECHO ARCHIVE COMPLETED

				)

			)

		)

ECHO ^>CLEANING %File_LOG_Archives%

	IF EXIST "%File_LOG_Archives%_temp.TXT" (

		FOR /F "DELIMS=" %%A IN ('TYPE "%File_LOG_Archives%_temp.TXT" ^| FindStr -i -v "7-Zip 4.65  Copyright" ^| Findstr -i -l -x -v "Scanning"') do echo %%A>>"%File_LOG_Archives%"

	)





etc...

Open in new window

0
 
LVL 51

Expert Comment

by:Bill Prew
ID: 33568844
In your example above, which file or pathnames could contain exclamation points?

~bp
0
 
LVL 10

Author Comment

by:ReneGe
ID: 33569389
This portion of the script will archive (zip) files to be later on deleted or updated from the source on a further Robocopy mirroring.

Robocopy will output the file list to -->%%A  then  --> !FileFull!

Therefore, the files containing the ! are put by users anytime/anywhere in the !BasePath_Source!\*.* /S

Thanks,
Rene
FOR /F "TOKENS= 2 DELIMS=	" %%A IN ('Robocopy "!BasePath_Dest!" "!BasePath_Source!" * /E /MIR /L /NJH /NJS /NS /NDL /XF *.mp3 *.wav *.avi *.wma *.iso /XD ISO "Virtual Machines *" Musique test ^| Findstr -V ^*') DO (

				SET PathSource=%%~pA

				SET SourceSize=%%~zA

				SET FileFull=%%A

Open in new window

0
 
LVL 10

Author Comment

by:ReneGe
ID: 33570719
I came up with the following sample working script.

Do you think this should be by best approach?

Thanks & cheers,
Rene

@echo off

SETLOCAL enabledelayedexpansion



SET SOURCE=C:\Batchfiles\TESTING\1

SET DESTIN1=C:\Batchfiles\TESTING\2a

SET DESTIN2=C:\Batchfiles\TESTING\2b



FOR /L %%A IN (1,1,2) DO CALL :CopyFiles "!DESTIN%%A!"



PAUSE

EXIT /B





:CopyFiles

SETLOCAL disabledelayedexpansion



SET DESTIN=%~1



IF NOT EXIST "%DESTIN%" MD "%DESTIN%"

FOR /R "%SOURCE%" %%A IN (*.*) DO (

	ECHO COPYING "%%A"  TO  "%DESTIN%"

	COPY /Y "%%A" "%DESTIN%" 

)



SETLOCAL enabledelayedexpansion

EXIT /b

Open in new window

0
 
LVL 51

Expert Comment

by:Bill Prew
ID: 33605172
How about this approach to keep it even simpler?

~bp
@ECHO OFF
SET SOURCE=C:\Batchfiles\TESTING\1
SET DESTIN="C:\Batchfiles\TESTING\2a","C:\Batchfiles\TESTING\2b"
FOR %%D IN (%DESTIN%) DO IF NOT EXIST "%%~D" MD "%%~D"
FOR /R "%SOURCE%" %%S IN (*.*) DO (
  FOR %%D IN (%DESTIN%) DO (
    ECHO COPYING "%%S"  TO  "%%~D"
    COPY /Y "%%S" "%%~D" 
  )
)
PAUSE
EXIT /B

Open in new window

0
 
LVL 10

Author Comment

by:ReneGe
ID: 33605252
Nice...

Thanks bp !

Cheers,
Rene
0

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Go is an acronym of golang, is a programming language developed Google in 2007. Go is a new language that is mostly in the C family, with significant input from Pascal/Modula/Oberon family. Hence Go arisen as low-level language with fast compilation…
A short article about a problem I had getting the GPS LocationListener working.
An introduction to basic programming syntax in Java by creating a simple program. Viewers can follow the tutorial as they create their first class in Java. Definitions and explanations about each element are given to help prepare viewers for future …
In this fourth video of the Xpdf series, we discuss and demonstrate the PDFinfo utility, which retrieves the contents of a PDF's Info Dictionary, as well as some other information, including the page count. We show how to isolate the page count in a…

759 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now