代码之家  ›  专栏  ›  技术社区  ›  Reman

在PowerShell中合并命令

  •  0
  • Reman  · 技术社区  · 5 年前

    我已经使用WindowsCmd shell很多年了,但我决定切换到PowerShell。

    我的命令在命令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"
    

    这很好,但我需要将这三个命令合并为一个命令。

    这就是我所做的:

    $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

    我做错什么了?

    4 回复  |  直到 5 年前
        1
  •  4
  •   Ansgar Wiechers    5 年前

    使用 ; 对于菊花链独立语句。使用管道 | )用于将一个命令的输出连接到另一个命令的输入。

    您还可以使用菊花链点访问属性和方法:

    (ls D:\MyFiles\workat.txt).LastWriteTime.ToString('yyy-MM-dd_HH-mm')
    

    但是,原始命令的最高级转换可能如下所示:

    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 通过管道。自从 复制项目 可以从管道中读取输入,您不需要指定源(因为源来自管道),只需要指定目标。由于您正在从管道读取数据,因此可以使用当前对象变量 $_ 要访问源对象的属性(注意:您需要一个脚本块,即表达式周围的花括号,以便工作)。

    第一个例子是使用格式运算符 -f 对于将日期插入路径字符串,第二个示例使用 Join-Path 用于从输入对象的各种属性构建目标路径的Cmdlet和字符串串联。

        2
  •  1
  •   rad_    5 年前

    试试这个:

    $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"
    
        3
  •  1
  •   wcarroll    5 年前

    管道需要显式数据,具体取决于调用的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"
    
        4
  •  1
  •   Robert Love    5 年前

    ()是将一个命令的结果嵌入到对另一个命令的调用中的一种方法。你基本上是用一套$rctime

    Copy-Item D:\MyFiles\workat.txt -destination "D:\MyFiles\workat_$((ls D:\MyFiles\workat.txt).LastWriteTime.ToString('yyy-MM-dd_HH-mm')).txt"