在Powershell脚本中使用CMD %~ mod

3duebb1j  于 2023-04-30  发布在  Shell
关注(0)|答案(2)|浏览(172)

我有一个运行ffmpeg的ps1脚本,我试图提示修剪开始时间,然后运行ffmpeg命令。我需要在powershell中使用或类似于%~的东西。
到目前为止,我已经尝试在另一篇文章中建议的字符串中转义%。即“%~”),但无济于事。以及谷歌省略了特殊字符从我的搜索查询,所以它没有给我带来很多信息,试图找到它的对应物在PS。
所以我的问题是,我可以在PS中使用什么来代替%~1%~dnp
验证码:

$start = Read-Host -prompt "trim start (ex. 00:00:00)"

Start-Process ffmpeg -ArgumentList "-i `"%~1`" -ss $start `"%~dnp`""

Read-Host -Prompt "Press Enter to exit"
omqzjyyz

omqzjyyz1#

补充briantist's helpful answer

tl;dr

  • 不要使用Start-Process启动 * 外部控制台应用程序 *,除非您明确希望它们在 * 单独的窗口 * 或 * 作为不同的用户 * 中运行-请参阅this answer了解背景信息,并参阅GitHub docs issue #6239了解何时使用Start-Process以及何时不使用Start-Process的指导。
  • 要进行Start-Process调用 synchronous,i.即,要等待它完成,请添加-Wait交换机。
  • 如果Start-Process是 * 不 * 需要的,请使用 * 直接调用 *,如下所示(如果可执行文件名或路径被引用或包含变量引用,请将调用操作符&放在它前面)。
  • %~1%~dpn1(根据您的问题更正)只能在 * 批处理文件 * 中工作,而不能在PowerShell脚本中工作(有关详细信息,请参阅底部部分)。
  • 你后来说你的脚本是从一个 * 基于注册表的快捷菜单命令定义 * 调用的。%1(或%V)占位符始终是从其调用菜单命令的文件系统项的完整路径。

定义要放置在注册表中的命令行,如下所示:

powershell -File "C:\path\to\your\script.ps1" "%V"
  • 注意:作为使用Read-Host -Prompt "Press Enter to exit"来防止窗口在完成后关闭的替代方案,您可以将-NoExit放在-File之前,这样可以保持会话活动,从而在传递给-File的脚本文件退出后窗口打开。

然后将PowerShell脚本重新定义为($args[0]cmd.exe%~1的PowerShell等效物):

$start = Read-Host -prompt "trim start (ex. 00:00:00)"

# Direct, synchronous invocation.
# Pass the first positional argument ($args[0]) both as-is and
# without its filename extension (invocation via a shortcut-menu command
# definition ensures that it is a full path).
ffmpeg -i $args[0] -ss $start ($args[0] -replace '\.[^.]*$')

Read-Host -Prompt "Press Enter to exit"
参数传递和-expansion的背景知识:
  • 在注册表中存储的***基于命令行的快捷菜单定义 * 中,%1是调用快捷菜单的文件系统项 * 的 * 完整路径 * 的占位符***(其他形式是%L%V,后者是唯一一种也适用于 * 背景 * 快捷菜单定义的形式,即%1。即在文件资源管理器窗口的背景中单击时起作用的快捷菜单项,隐式地针对 * 目录 *)。
  • 双引号 * 不会 * 自动执行,因此使用的安全形式是"%1"(或者,更普遍地,"%V"),i。e.将占位符显式包含在"..."中,作为存储在注册表中的命令行的一部分。
  • 批处理文件***(*.cmd.bat)中,由cmd.exe解释,%1引用调用时传递的 * 第一个参数**-它可能是也可能不是文件系统路径,也可能不是 * 完整 * 路径(%2引用 * 第二个 * 参数,...,而%0指的是手头的批处理文件,反映了调用的路径 *)。
    *如果参数是用"..."括起来传递的,则%1 * 包含 * 双引号,但您可以使用%~1删除它们
  • 此外,*在 * 是 * 文件系统路径~的参数中,后面可以跟一个(组合) 字母 *,表示路径**的 * 组件 *,特别是驱动器规格的d。(例如,d:),p用于完整的驱动器相对路径,以\(e.g,\Windows\System32\),n用于 base 文件名(即文件名 * 不带扩展名 *(e.例如,foo),以及用于扩展的x(例如,foo)。例如,.txt)-运行cmd /c call /?了解详细信息和附加字母。
  • 与单独使用~一样,结果字符串中的所有双引号都 removed
  • 例如,如果"one two.txt"作为第一个参数传递,并且当前目录是C:\path\to,则%~dpn1将扩展为逐字的C:\path\to\one two
    *PowerShell脚本*.ps1)中:
  • 自动**$args**变量包含作为 array 传递的(位置)参数,其元素 never 包含任何在命令行上传递的(未转义的)封闭"..."
  • 因此,PowerShell的**$args[0]相当于cmd.exe%~1**(注意索引0是指 first 元素,因为PowerShell是基于此构建的。NET,其数组索引基于0)。
  • 请注意,PowerShell还支持 named 参数,这些参数基于 * 正式声明的参数 *,这对于健壮性来说是更可取的-请参阅briantist的回答。
    cmd.exe样式的参数扩展(如%~dpn1 没有 * 直接PowerShell等效项-您必须改用PowerShell的cmdlet和运算符。
  • 假设第一个参数指向一个 existing 文件,则等效的命令为:
# Convert to a full, file-system-native path and remove the extension.
(Convert-Path -LiteralPath $args[0]) -replace '\.[^.]*$'
  • 可悲的是,将 * 不存在 * 的文件系统路径(例如即将 * 创建 * 的文件)转换为完整的文件系统本地路径更加复杂,因为Convert-Path,从PowerShell 7开始。3.3,只支持 * 现有 * 路径(有关背景信息,请参阅this answer):
# Windows PowerShell
[IO.Path]::GetFullPath([IO.Path]::Combine($PWD.ProviderPath, $args[0]))

# PowerShell (Core) 7+ (simpler)
[IO.Path]::GetFullPath($args[0], $PWD.ProviderPath)
  • 类似地,没有直接等价于cmd.exe%0来引用正在运行的批处理文件/脚本本身,但是有两个 * 自动变量 *:
  • $PSScriptRoot包含运行脚本所在的 directory 的完整路径。
  • $PSCommandPath包含运行脚本 * 本身 * 的完整路径。
33qvvth1

33qvvth12#

直接的等价物可能是使用$args来访问传入的参数。例如,你可以执行$args[0]来得到%~1的等价物。
%~1中的波浪号~删除了周围的引号,这不是您在从PowerShell脚本中的参数或参数阅读时需要担心的事情。

参数

您可能希望显式地为脚本定义参数,而不是$args,这可以通过脚本顶部的param()块来完成。你甚至可以把你的开始时间作为一个参数,然后提示它是否为空。

param(
    $Path,
    $Start,
    $Destination
)

if (-not $Start) {
    $Start = Read-Host -prompt "trim start (ex. 00:00:00)"
}

Start-Process ffmpeg -ArgumentList @(
    "-i"
    $Path
    "-ss"
    $Start
    $Destination
)

Read-Host -Prompt "Press Enter to exit"

拨打电话:

<script>.ps1 -Path path/to/source -Destination /path/to/destination -Start 12:34:56

(if你离开-Start了,它会提示)
请注意,%~dnp本身可能无效。那里应该有个号码吗或者如果你在FOR循环中使用它的话是一个字母?现在我将忽略它,并为目的地取一个新参数。
我还将Start-Process调用改为使用数组形式的参数,因为我觉得这样更简洁,但如果愿意,也可以将其改回一个大字符串。
阅读更多关于高级函数的内容,了解如何使参数成为强制参数(如果缺少参数,将自动提示输入参数),验证值,设置类型等。

引用

相关问题