如何使用拖放功能让Windows cmd FOR“play-nice” [英] How do I get Windows cmd FOR to 'play-nice' with drag-n-drop

查看:185
本文介绍了如何使用拖放功能让Windows cmd FOR“play-nice”的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个非常简单的小批处理脚本。设计大纲很简单...我想要触摸每个文件已放弃


  1. 有在桌面上的一个Windows快捷方式调用批处理(.cmd)脚本。

  2. 使用Windows资源管理器选择一些文件


  3. 脚本循环在图标上的文件列表中。

  4. 脚本使用 FOR 命令一次调用命令一个文件。

无论如何几种情况,结果是奇怪的(至少说)。最糟糕的例子是一个无限循环,崩溃了cmd.exe。这是命令文件。这里有额外的打印和暂停,所以我可以看到这个行为。

  @echo off 
@title touch
@echo。
cd> z:\ $$$ \base.tmp
set / p base =< z:\ $$$ \base.tmp
@rem
@echo ^ folder:%base%
@echo ^ INPUT:[%*]
@echo。
@pause
@echo。 (%*)中的/ d %% x
DO(
@echo ^ RAW:[%% x]
@echo ^ each - ^> [%%〜x]
@echo ^ each - ^> [%%〜fx]
attrib%%〜fx
touch%%〜fx
echo。
@pause
echo。

@echo。
@echo ^ [done]
@echo。
@pause

最有问题的输出是对我的混淆的一个来源,参见:example我把 attrib 命令放入,因为它是一个'tame'系统.exe。



当您注释触摸命令时,外观与 attrib 。我唯一可以肯定的是,文件名与空格会导致问题。例如,在 每个 行中,我看到了一些例子:




  • each - > [Z:\tmp\Z:\tmp\C ++ Recipes.pdf]

  • G:\\ \\_xfer_\ -m



第一个似乎是FOR循环扩展的问题,如何处理引号(),而第二个似乎是MSYS touch.exe命令的超出错误。



还有一些鱼会继续当您将链接(快捷方式)文件传递到脚本时。



我尝试过许多不同版本的FOR语法和循环变量转义到边我的第一个问题是大脑的信任是:


  1. 什么是适用于FOR和循环变量的扩展吗?

同样,由于它已经成为一个谜...


  1. 无限循环如何发生,有没有办法防止?

  2. 有人有链接fo r文档和/或使用Window拖放的FOR的示例?
  3. 脚本如何显示:
    工作文件夹.. 。
    G:\_xfer _
    当字符串:工作文件夹,不在.cmd脚本。而且,有一个版本的命令是: echo工作文件夹:

它有帮助,我把一个小脚本叫做drop.cmd也在下面。作为最后一点,我怀疑Windows的MSYS / GNU命令行处理程序有一个错误:




  • 看来,当 * args 包含一个带有不平衡引号的字符串 - 可以关闭预约。



我从下面的MSYS touch 尾部命令获得类似的输出。



我即将签署。还有一件事要考虑。有没有人可以使用脚本或诊断程序来解开这个 ?



示例1



 文件夹:G:\_xfer_ 
INPUT:[G:\_xfer_\00__zip(on D).lnkG :\_xfer_\#trash.lnk]

按任意键继续。 。 。

RAW:[G:\_xfer_\00__zip(on D).lnk]
each - > [G:\_xfer_\00__zip(on D).lnk]
each - > [G:\_xfer_\00__zip(on D).lnk]
AG:\_xfer_\00__zip(在D上).lnk
全部... G:\_xfer_\00__zip (在D).lnk
一个... G:\_xfer_\00__zip
两个...(在


工作文件夹...
G:\_xfer_

touch -m -cG:\_xfer_\ -m

工作文件夹...
G :\_xfer_

touch -m -cG:\_xfer_\ -m


/ pre>

最终坠毁了一个stackoverflow!



drop.cmd



  @echo off 
@title%〜1
@echo。
cd> z:\ $$$ \\ \\base.tmp
set / p base =< z:\ $$$ \base.tmp
@rem
@echo ^ drop folder:%base%
@echo ^ INPUT:[%*]
@echo。
@pause
rem
@echo。
for %% x in(%*)DO(
@echo ^ RAW:[%% x]
@echo ^ each - ^> [%%〜x]
@echo。
@pause

@echo。
@ec ho ^ [done]
@echo。
@pause


解决方案

获取批处理文件句柄丢弃的文件有时会很困难。任何拖动的文件,其名称中的空格将被引用,但不包括特殊字符(& )但不包含空格的文件。这将导致解析器使用%* 处理参数的问题。



但是,来自jeb'answer 的href =https://stackoverflow.com/a/5472168/2861476>代码和抛光by @dbenham 来解决 相当打印窗口%path%变量 (谢谢你们),只有从命令行调用($ arguments $)code>%* 应该格式正确)或从%cmdcmdline%(保存用于启动当前 cmd的命令行实例)删除后,我们可以执行类似

  @echo off 
setlocal enableextensions disabledelayedexpansion
setvar =

rem确定调用来源
setlocal enabledelayedexpansion
调用: detectDrop!cmdcmdline!
endlocal
如果不是错误级别1 goto:dropped

:commandLine
rem从命令行调用
setdropped =
如果 %〜1==goto done
set var =%*
setvar =%var:=%
goto:process

:drop
rem从资源管理器调用
setdropped = 1
setvar =%cmdcmdline:=%
setvar =%var:* / c=%
setvar =%var:*=%
setvar =%var:〜0,-2%

:process
如果没有定义var goto:done

rem从dbenham的答案改为[https://stackoverflow.com/a/7940444/2861476]

setvar =%var:^ = ^^%
setvar =%var:& = ^&%
setvar =%var:| = ^ |%
setvar =%var:< = ^<%
setvar =%var:> = ^>%
setvar =%var: = ^ ^%
set var =%var:=%
setvar =%var:=Q%
setvar =%var: SS%
setvar =%var:^ ^ =%
setvar =%var:=%
set local enabledelayedexpansion
setvar =!var:Q =!
%% a in(!var:SS =!)do(
if!!==endlocal

rem Here我们参考了通过/放弃的元素
如果%% a neqecho%%〜fa


goto:done

:detectDrop cmdcmdline
if / i%〜1==%comspec%if / i%〜2==/ cexit / b 0
exit / b 1

:完成
如果定义掉(暂停和退出)

注意:对不起,没有彻底测试。也许有一些情况会使它失败。


I had a very straight forward little batch script. The design outline is simple enough ... I want to touch every file 'dropped'.

  1. There is a Windows short-cut on the desktop that calls a batch (.cmd) script.
  2. Select some files with Windows Explorer
  3. Drag-n-Drop the selection onto either the short-cut icon or the command file directly.
  4. The script loops over the list of files dropped onto the icon.
  5. The script uses the FOR command to call the command one file at a time.

Anyway there are several circumstances where the result is strange (to say the least). The worst example is an infinite loop that crashes cmd.exe. Here is the command file. There are extra prints and pauses here so I can watch the behaviour.

  @echo off
  @title  touch
  @echo.
  cd > z:\$$$\base.tmp
  set /p base= < z:\$$$\base.tmp
  @rem
  @echo  ^  folder: %base%
  @echo  ^  INPUT:  [%*]
  @echo.
  @pause
  @echo.
  for /d  %%x  in  (%*)  DO (
      @echo ^    RAW:      [%%x]
      @echo ^    each --^>  [%%~x]
      @echo ^    each --^>  [%%~fx]
      attrib "%%~fx"
      touch "%%~fx"
    echo.
    @pause
    echo.
)
@echo.
@echo ^  [done]
@echo.
@pause

The most problematic output is a source of confusion to me, see: example 1. I put the attrib command in because it is a 'tame' system .exe.

When you comment-out the "touch" command, the look works with just attrib most of the time. The only thing I can say for sure is that file names with spaces cause problems. For example in the echo-ed "each" lines, I've seen examples like:

  • each --> [Z:\tmp\"Z:\tmp\C++ Recipes.pdf"]
  • "G:\_xfer_\-m"

The first seems to be a problem with the FOR loop expansion and how it deals with quotes("). While the second appears to be a out of bounds error with the MSYS touch.exe command.

There's also something fish that goes on when you pass a link (short-cut) file to the script.

I've tried many different versions of both the FOR syntax and the loop-variable escaping to side-step the issue. After all my primary purpose is to have a GUI touch command. My first question for the brains trust is:

  1. What is the appropriate FOR and loop-variable expansion to use for this?

As well, since it has become a mystery ....

  1. How does the infinite loop occur and is there a way to prevent it?
  2. Does someone have a link for documentation and/or examples of FOR with a drag-n-drop with Window?
  3. How can the script just show: Working folder ... G:\_xfer_ When the string: "Working folder", which is NOT in the .cmd script. And, there was once a version that had the command: echo Working folder:

It it helps, I put a small script called, "drop.cmd" below as well. As a final point, I suspect there's a bug in the MSYS /GNU command-line handler for Windows:

  • It seem that, When the *args that was passed contains a string with unbalanced quotes -- It can go off the reservation.

I get similar output to that in example 1, below from the MSYS touch and from tail commands.

I was about to sign-off. There is one more thing, to consider. Does anyone have a script or diagnostic I might use to 'unravel' this ball-of-wool?

example 1

   folder: G:\_xfer_
   INPUT:  ["G:\_xfer_\00__zip (on D).lnk" G:\_xfer_\#trash.lnk]

Press any key to continue . . .

    RAW:      ["G:\_xfer_\00__zip (on D).lnk"]
    each -->  [G:\_xfer_\00__zip (on D).lnk]
    each -->  [G:\_xfer_\00__zip (on D).lnk]
A            G:\_xfer_\00__zip (on D).lnk
  all ... G:\_xfer_\00__zip (on D).lnk
  one ... G:\_xfer_\00__zip
  two ... (on


   Working folder ...
G:\_xfer_

touch -m -c  "G:\_xfer_\-m"

   Working folder ...
G:\_xfer_

touch -m -c  "G:\_xfer_\-m"
    :
    :

And eventually crashed with a stackoverflow!

drop.cmd

@echo off
@title  %~1
@echo.
cd > z:\$$$\base.tmp
set /p base= < z:\$$$\base.tmp
@rem
@echo  ^  drop folder: %base%
@echo  ^  INPUT:       [%*]
@echo.
@pause
rem
@echo.
for   %%x  in  (%*)  DO ( 
    @echo ^    RAW:      [%%x]
    @echo ^    each --^>  [%%~x]
    @echo.
    @pause
)
@echo.
@echo ^  [done]
@echo.
@pause

解决方案

Getting a batch file handle dropped files can be sometimes difficult. Any dragged file with spaces in its name will be quoted, but a file with special characters (&) but without spaces will not be quoted. This will lead to problems with the parser handling the arguments to the file using %*.

But taking the code from jeb' answer and polished by @dbenham to solve the problem of "Pretty print windows %path% variable" (thank you both), and retrieving the arguments from %* only when called from command line (where arguments "should" be well formed) or from %cmdcmdline% (that hold the command line used to start the current cmd instance) when dropped, we can do something like

@echo off
    setlocal enableextensions disabledelayedexpansion
    set "var="

    rem Determine call origin
    setlocal enabledelayedexpansion
    call :detectDrop !cmdcmdline!
    endlocal
    if not errorlevel 1 goto :dropped

:commandLine
    rem Invoked from command line
    set "dropped="
    if "%~1"=="" goto done
    set var=%*
    set "var=%var:"=""%"
    goto :process

:dropped
    rem Invoked from explorer
    set "dropped=1"
    set "var=%cmdcmdline:"=""%"
    set "var=%var:*/c """"=%"
    set "var=%var:*"" =%"
    set "var=%var:~0,-2%"

:process
    if not defined var goto :done

    rem Adapted from dbenham's answer at [https://stackoverflow.com/a/7940444/2861476]

    set "var=%var:^=^^%"
    set "var=%var:&=^&%"
    set "var=%var:|=^|%"
    set "var=%var:<=^<%"
    set "var=%var:>=^>%"
    set "var=%var: =^ ^ %"
    set var=%var:""="%
    set "var=%var:"=""Q%"
    set "var=%var:  ="S"S%"
    set "var=%var:^ ^ = %"
    set "var=%var:""="%"
    setlocal enabledelayedexpansion
    set "var=!var:"Q=!"
    for %%a in ("!var:"S"S=" "!") do ( 
        if "!!"=="" endlocal

        rem Here we have a reference to the passed/dropped element
        if %%a neq "" echo "%%~fa"

    )
    goto :done

:detectDrop cmdcmdline
    if /i "%~1"=="%comspec%" if /i "%~2"=="/c" exit /b 0
    exit /b 1

:done    
    if defined dropped ( pause & exit )

note: sorry, not thoroughly tested. Maybe there is some case that will make it fail.

这篇关于如何使用拖放功能让Windows cmd FOR“play-nice”的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆