如何让 Windows cmd FOR 通过拖放操作“玩得很好" [英] How do I get Windows cmd FOR to 'play-nice' with drag-n-drop

查看:17
本文介绍了如何让 Windows cmd FOR 通过拖放操作“玩得很好"的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个非常直接的小批处理脚本.设计大纲很简单......我想触摸每个文件'dropped'.

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

  1. 桌面上有一个调用批处理 (.cmd) 脚本的 Windows 快捷方式.
  2. 使用 Windows 资源管理器选择一些文件
  3. 直接将选择拖放到快捷图标或命令文件上.
  4. 脚本循环遍历放置在图标上的文件列表.
  5. 脚本使用 FOR 命令一次调用一个文件.
  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.

无论如何,在某些情况下结果很奇怪(至少可以这么说).最糟糕的例子是导致 cmd.exe 崩溃的无限循环.这是命令文件.这里有额外的打印和暂停,所以我可以观察行为.

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:$$$ase.tmp
  set /p base= < z:$$$ase.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

最有问题的输出让我感到困惑,请参阅:示例 1.我将 attrib 命令放入其中,因为它是一个驯服"的系统 .exe.

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.

当您注释掉触摸"命令时,该外观仅在 attrib 大部分时间 中起作用.我唯一可以肯定的是,带有空格的文件名会导致问题.例如,在 echo-ed "each" 行中,我看到了如下示例:

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:

  • 每个 -->[Z: mp"Z: mpC++ 食谱.pdf"]
  • G:\_xfer_-m"

第一个似乎是 FOR 循环扩展以及它如何处理引号 (") 的问题.而第二个似乎是 MSYS touch.exe 命令的越界错误.

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.

我已经尝试了许多不同版本的 FOR 语法和循环变量转义来回避这个问题.毕竟我的主要目的是拥有一个 GUI 触摸命令.我对智囊团的第一个问题是:

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. 为此使用什么合适的 FOR 和循环变量扩展?

同样,既然它已经成为一个谜......

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

  1. 无限循环是如何发生的,有没有办法防止它?
  2. 是否有人提供带有 Window 拖放功能的 FOR 文档和/或示例的链接?
  3. 脚本如何只显示:工作文件夹...G:\_xfer_当字符串:工作文件夹"时,它不在 .cmd 脚本中.而且,曾经有一个版本有这个命令:echo Working folder:
  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:

它有帮助,我也在下面放了一个名为drop.cmd"的小脚本.最后一点,我怀疑 Windows 的 MSYS/GNU 命令行处理程序存在错误:

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:

  • 似乎,当传递的 *args 包含带有不平衡引号的字符串时 -- 它可以取消保留.
  • It seem that, When the *args that was passed contains a string with unbalanced quotes -- It can go off the reservation.

我从 MSYS touchtail 命令获得了与示例 1 中类似的输出.

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?

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

Press any key to continue . . .

    RAW:      ["G:\_xfer_0__zip (on D).lnk"]
    each -->  [G:\_xfer_0__zip (on D).lnk]
    each -->  [G:\_xfer_0__zip (on D).lnk]
A            G:\_xfer_0__zip (on D).lnk
  all ... G:\_xfer_0__zip (on D).lnk
  one ... G:\_xfer_0__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!

@echo off
@title  %~1
@echo.
cd > z:$$$ase.tmp
set /p base= < z:$$$ase.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 %*.

但是从 jeb 的答案中获取 代码由@dbenham 打磨 解决"Pretty print windows %的问题path% 变量" (谢谢你们),并且仅在从命令行调用时才从 %* 中检索参数(其中参数 "应该" 格式正确)或从 %cmdcmdline% (保存用于启动当前 cmd 实例的命令行)删除时,我们可以执行类似的操作

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 通过拖放操作“玩得很好"的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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