Bash 管道 : split input after 1st line, 在第 1 行和其余行上运行不同的命令

标签 bash line pipe

我有一个备份脚本,它通过 ssh 复制文件并在传输过程中创建哈希文件。另外 pv 用于显示进度条:

ssh $host "cat '$src_dir/$filename'" \
    | pv --bytes --eta --progress --rate --timer --wait  $opts \
    | tee "$filename" \
    | sha1sum > "$filename.sha1"

为了正确显示进度条,我需要将文件的大小传递给pv。目前,我通过给出最后一个备份文件的大小来做到这一点。

重要的是,所有事情都通过 1 个 ssh 调用完成,因为我不想为 1 个备份多次授权。 SSH key 正在使用中,但使用密码保护。

我的想法是调用 ssh $host "stat -c%s '$src_dir/$filename'; cat '$src_dir/$filename'" 并在第一行之后分割输出。我可以读取文件大小,然后对输入的其余部分调用 pv

备份脚本工作正常。这只是一个为了好玩的练习。任何想法都值得赞赏,但我不会完全重写整个脚本。特别是我不会切换到 scp 因为我无法在传输过程中进行哈希处理,而且我不想信任本地存储(当然我愿意,但是为什么我们要这样做)无论如何都要进行哈希处理吗?)。

更新:我最终这样做了:

ssh $host "cd '$src_dir' && stat -c%s '$filename' && sha1sum '$filename' && cat '$filename'" | {
        read size;
        head -n 1 > "$filename.sha1";
        pv --bytes --eta --progress --rate --size $size --timer --wait > "$filename"
    }

它工作得很好,并且具有哈希值在远程站点计算的优点。因此,不仅在写入磁盘之前,而且在进行网络传输之前。

最佳答案

在此示例中,我在 OSX 上使用 stat,它使用 z 作为大小的格式字符串:

$ { stat -f %z input; cat input; } | { read s; echo $s; }

将第一个命令列表替换为您的 ssh 调用,并将 echo 替换为您的 pv 列表,然后就可以开始了。换句话说,您的最终命令应该是:

$ ssh $host "stat -c%s '$src_dir/$filename'; cat '$src_dir/$filename'" | {
    read size;
    pv --bytes --eta --progress --rate --timer --wait --size $size |
    tee "$filename" |
    sha1sum; } > "$filename.sha1"

有几件事需要注意:我无权访问 pv,也没有检查上述内容。 我用管道符号替换了你的续行,因为我认为 看起来更好了。

另一个想法:在管道的右侧,您可以这样做:

{ pv --bytes ... --size $( sed 1q ) |
...

这绝对依赖于 sed 不读取第一个换行符,我不知道这是否由任何标准保证,但它适用于...哦天啊,我的 sed 不支持 --version, -?,或 -h,而且我不太了解 OS X 的包管理系统,无法告诉你我正在运行什么 sed。它适用于某些版本的 BSD sed...

关于Bash 管道 : split input after 1st line, 在第 1 行和其余行上运行不同的命令,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9226821/

相关文章:

powershell - 当管道整数数组时 $_ 变量为空?

regex - 如何制定特定的正则表达式

java - 将管道应用程序的控制台文本捕获到另一个应用程序

javascript - 获取 'Could Not Be Found' 错误 : Custom Pipe in Angular 2 App

ios - CAShapeLayer 更改 lineWidth 导致崩溃

java - 如何判断一个点是在线段的左侧还是右侧?

c# - 清除控制台中的一行

linux - 使用monit重启ffmpeg进程

java - 如何使用Java在windows上启动bat文件,在linux上启动sh文件从特定目录运行

string - 如何将字符串转换为 Bash 中的所有空格?