如何将 grep 输出输入到 scp?

如何将 grep 输出输入到 scp?

我有一个文件,其中每一行都是一个文件名。文件内容:

file1
file2
file3
...

然后我运行一个grep命令来获取文件名列表的子集。

如何将grep命令的输出输入到scp?我尝试过xargs$()都没有成功...

答案1

无需使用xargs

for file in $(grep <some-pattern> <filelist>); do scp $file <remote>; done;

在哪里

  • <some-pattern>是你的grep模式
  • <filelist>是你的文件列表
  • <remote>scp是你的命令的远程端

循环for将遍历生成的每一行grep并将其传递给,您可以在和$file之间执行的命令中重复使用它。dodone

另请参阅:高级 Bash 脚本指南:循环

答案2

要迭代每行一个名称的文件名列表,您有几种可能性:

  • 使用命令替换将文件放入 shell 中的文件名列表中。您需要采取预防措施,因为您不能将命令替换放在双引号中,因为命令替换的结果需要拆分为单词。您需要关闭通配符并设置为IFS仅在换行符上拆分单词。

    set -f; IFS='
    '
    scp -- $(…) remote.example.com:
    
  • 使用read内置函数循环处理文件名。同样,您需要小心,因为它会特殊read处理反斜杠和$IFS字符。

    … | while IFS= read -r x; do scp -- "$x" remote.example.com: done
    
  • 您可以使用 GNU xargs,但必须谨慎行事,因为 xargs 要求其输入采用奇怪的引用格式。您必须传递选项-d '\n'以明确选择换行符作为输入分隔符,并关闭空格和 的特殊行为\'"

    … | xargs -d '\n' -I {} scp {} remote.example.com:
    

    的唯一优点xargs是它可以将多个参数组合到一次调用中,直到达到命令行长度限制,但这仅在参数最后传递给命令时才有效。您可以通过中间调用来实现这一点sh,但这很少值得。

    … | xargs -d '\n' sh -c 'scp -- "$@" "$0"' remote.example.com:
    
  • 一种更简单的使用方法xargs是获取以空字符分隔的列表,而不是以换行符分隔的列表。这需要选项-0,GNU xargs 和最近的 *BSD 都支持该选项。如上所述,将参数推入非最终位置需要一些工作。

    … | tr '\n' '\0' | xargs -0 sh -c 'scp -- "$@" "$0"' remote.example.com:
    

如果您打算使用正则表达式过滤文件名,则该部分将起作用。如果您打算过滤文件内容,请使用上述技术之一将文件名提供给,例如grep NAME_REGEXP /path/to/filenames.listgrep

set -f; IFS='
'
scp -- $(grep -l CONTENT_REGEXP -- $(cat /path/to/filenames.list)) \
    remote.example.com:

绕过 shell 困难的另一种可能性是使用rsync及其--files-from选项。假设文件名都是相对于当前目录的:

grep NAME_REGEXP /path/to/filenames.list |
rsync -a --files-from - . remote.example.com:

答案3

用于read逐行解析输出(https://stackoverflow.com/a/7039208(英文): grep <some-pattern> <filelist> | while read file; do scp $file <remote>; done;

相关内容