简体   繁体   中英

Spaces in filenames using forfiles and 7zip

I am writing a script to zip up old files, using forfiles for the looping and 7za for the zipping. I have been struggling with how to deal with spaces in the filenames, and although I have found a solution that seems to work, not understanding why has me nervous about deploying it to production.

Here is the command that appears to work:

forfiles -p%rootLogDir% -s -m*.log -d-14 -c"cmd /c 7za a -tzip """@PATH\@FILE-%date%.zip""" """@PATH\@FILE""""

Note that the path and filename arguments to 7za have 3 (yes THREE) sets of quotes around them. One set of quotes does nothing, two sets of quotes resulted in the script adding every file in the directory into the archive, rather than the one specified, and three appears to work.

Can anyone explain why so many are required? I would have thought that after one set the rest are superfluous, but apparently I am wrong.

( forfiles is a cmd.exe subcommand? If so, you should re-tag your question with one of the many (MS)windows tags available. )

Quoting can be a maddening experience, even for people with much experience in shell and bat scripts.

@BugFinder's msg is appropriate, and I would add that 3 dbl-quotes is one way to "quote" a single double-quote char.

You are working 'with' the command processor (cmd.exe?). You type a command (with 1 or more words or operators), ie

myCommand /s /d %dir% file1 file2 > sumFile

and then press the enter key. The command processor doesn't just start executing the command you have submitted, it scans the line, looking for special case words and symbols, like variable names. In Unix shells environment variables look like $varName or ${varName} . In.bat files %var% or %%v%% . That variable has to be converted into a value.

That is just one pass that the command processor makes, there are others. But for your needs, the cmd-processor is scanning for word sets that should be taken as one word. If you have a var="one two" , not surrounding the value side with quotes will confuse any command that has to process it. it will look like var=one.... two (separate word, right?).

So if for some reason you need to pass thru a double-quote char to a lower layer of processing, you have to follow the command processor rules, quote things as needed and then everything will work ok.

Just as "word" is a quoted word, """ is a quoted double quote. After the command processor does it normal processing of quotes, the middle double quote will still be remaining in the command processor's 'view' of what is on the command line (after variable have been expanded, and all the other order of processing rules have been followed.)

Whew!

So to wrap it up, you wrote in a comment

But then """ -> "" -> " ,

No, """ => "

so why is one quote not sufficient?

Because using """ is one way to have the command processor leave a stand-alone double quote char remain on the command line and not blow up.

Or does the first condensed double quote gain some sort of magical power?

No magical powers, note that your command has a later """ s. Each set is leaving 1 " char for later processing.

As @BugFinder points out, \" might be sufficient, but I'm not sure which command processor or shell you are using, so I can't run a test.

Finally, Per an excellent reminder written by belisarius,

Allow me to welcome you to StackOverflow and remind three things we usually do here: 1) As you receive help, try to give it too, answering questions in your area of expertise 2) Read the FAQs, http://tinyurl.com/2vycnvr , 3) When you see good Q&A, vote them up by using the gray triangles, http://i.stack.imgur.com/kygEP.png , as the credibility of the system is based on the reputation that users gain by sharing their knowledge. Also remember to accept the answer that better solves your problem, if any, by pressing the checkmark sign, http://i.stack.imgur.com/uqJeW.png

I hope this helps.

At a quick guess, like a number of things """ = ", eg 2 quotes round a quote.. a \" may have also been sufficient.

All filenames and paths which contain spaces must be quoted.

Next, regarding your question, how about stating the path like:

start /max /d"C:\Program files\foo\" ba.exe -somearguments

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM