我已经使用Windows cmd shell多年了,但是我决定切换到Powershell。
我在cmd shell中的命令,用于对添加日期和时间的文件进行备份:
copy /-Y "D:\MyFiles\workat.txt" d:\bkp_workat_'. strftime("%Y-%m-%d_%H-%M", getftime('D:\MyFiles\workat.txt')) .'.txt'
workat.txt --> bkp_workat_2019-02-14_17-52.txt
powershell中的相同命令:
$RCTime = (ls D:\MyFiles\workat.txt).LastWriteTime
$myDate = $RCTime.ToString('yyy-MM-dd_HH-mm')
Copy-Item D:\MyFiles\workat.txt -destination "D:\MyFiles\workat_$myDate.txt"
这很好用,但我需要将3个命令合并为一个命令。
这就是我所做的:
$RCTime = (ls D:\MyFiles\workat.txt).LastWriteTime | $myDate = $RCTime.ToString('yyy-MM-dd_HH-mm') | Copy-Item D:\MyFiles\workat.txt -destination "D:\MyFiles\workat_$myDate.txt"
这会导致错误:Expressions are only allowed as the first element of a pipeline
我怎么了?
答案 0 :(得分:4)
使用;
进行菊花链式独立语句。使用管道(|
)将一个命令的输出连接到另一个命令的输入。
您还可以通过菊花链方式对属性和方法进行点访问:
(ls D:\MyFiles\workat.txt).LastWriteTime.ToString('yyy-MM-dd_HH-mm')
但是,原始命令中最PoSh的翻译可能看起来像这样:
Get-Item 'D:\MyFiles\workat.txt' |
Copy-Item -Destination { 'D:\MyFiles\workat_{0:yyy-MM-dd_HH-mm}.txt' -f $_.LastWriteTime }
或者这个:
Get-Item 'D:\MyFiles\workat.txt' |
Copy-Item -Destination { Join-Path $_.DirectoryName ($_.BaseName + $_.LastWriteTime.ToString('_yyy-MM-dd_HH-mm') + $_.Extension }
Get-Item
从给定的路径生成一个FileInfo
对象,并将其通过管道传递给Copy-Item
。由于Copy-Item
可以从管道读取输入,因此您无需指定源(如来自管道),而只需指定目标。并且由于您正在从管道中读取内容,因此可以使用当前对象变量$_
来访问源对象的属性(注意:您需要一个脚本块,即表达式周围的大括号,该脚本块才能起作用)。
第一个示例使用格式运算符-f
将日期插入到路径字符串中,第二个示例使用Join-Path
cmdlet和字符串串联以根据文件的各种属性构建目标路径输入对象。
答案 1 :(得分:1)
尝试一下:
$RCTime = (ls C:\MyFiles\workat.txt).LastWriteTime;$myDate = $RCTime.ToString('yyy-MM-dd_HH-mm') | Copy-Item D:\MyFiles\workat.txt -destination "C:\MyFiles\workat_$myDate.txt"
您正在尝试将另一个变量传递给另一个变量。因此,为什么会出现错误。只是好奇,为什么要将所有结构都构造成一行?这样做是个好习惯:
$RCTime = (ls C:\MyFiles\workat.txt).LastWriteTime
$myDate = $RCTime.ToString('yyy-MM-dd_HH-mm')
Copy-Item D:\MyFiles\workat.txt -destination "C:\MyFiles\workat_$myDate.txt"
答案 2 :(得分:1)
()是一种将一个命令的结果嵌入到另一个命令的调用中的方法。您基本上是使用$ RCTime设置的
Copy-Item D:\MyFiles\workat.txt -destination "D:\MyFiles\workat_$((ls D:\MyFiles\workat.txt).LastWriteTime.ToString('yyy-MM-dd_HH-mm')).txt"
答案 3 :(得分:1)
管道会根据调用的CMDLET期望显式数据。在您的示例中,您要设置等于CMDLET的变量,然后尝试将其通过管道传递给下一个命令。实际上,每行只能设置一个变量,但是如果您将分号的管道切换出来,它应该可以工作,但不是最佳实践。
如果您想做一个真正的班轮,您需要嵌套通话,看起来像这样。
Copy-Item D:\MyFiles\workat.txt -destination "D:\MyFiles\workat_$($(Get-ChildItem D:\MyFiles\workat.txt).LastWriteTime.ToString("yyyy-MM-dd_HH-mm")).txt"