从远程 ssh 服务器上的 tar 存档中提取某些文件

Extracting certain files from a tar archive on a remote ssh server

我在远程服务器上运行进行了多次模拟(通过ssh)。这些模拟的结果作为 .tar 存档存储在此远程服务器上的存档目录中。

我想做的是编写一个 bash 脚本,它通过 ssh 连接到远程服务器并从每个 .tar 存档中提取所需的输出文件到我本地的单独文件夹中硬盘。

这些文件夹应与文件来源的 .tar 文件同名(举个例子,假设模拟 1 的输出存储在存档 S1.tar 上远程服务器,我希望将此 .tar 存档中的所有“.dat”和“.def”文件提取到本地驱动器上的目录 S1。

对于提取本身,我正在尝试:

for f in *.tar; do
(
    mkdir ../${f%.tar}
    tar -x -f "$f" -C ../${f%.tar} "*.dat" "*.def"
)
done
wait

每个 .tar 文件大约 1GB,而且数量很多。所以下载所有东西太花时间了,这就是为什么我只想提取必要的文件(见上面代码中的扩展名)。

现在,当我的本地驱动器上有 .tar 文件时,代码可以完美运行。但是,我不知道如何才能做到这一点而不必首先从服务器下载所有 .tar 档案。

当我第一次通过 ssh username@host 连接到远程服务器时,终端会停止运行脚本并连接到服务器。

顺便说一句,我在 VS Code 中执行此操作,运行 通过我的 MacBook 上的终端编写脚本。

我希望我已经描述清楚了。感谢您的帮助!

通过 SSH

tar 的结果与文件名一起返回

要获取您希望从 .tar 文件中检索的数据,您需要将 tar 的结果传递给带有 --to-command 选项的命令字符串。在下面的示例中,我们将 运行 三个命令。

# Send the files name back to your shell
echo $TAR_FILENAME

# Send the contents of the file back
cat /dev/stdin

# Send EOF (Ctrl+d) back (note: since we're already in a $'' we don't use the $ again)
echo '[=10=]4'

在您的 shell 中捕获信息后,我们可以开始处理数据。这是一个三步过程。

  1. 获取文件名
    • 请注意,在此代码中,我们根本不处理目录(只是将它们剥离;即 dir/1.dat -> 1.dat
    • 您可以编写代码来为文件创建目录,方法是将正斜杠 / 替换为空格并遍历每个目录名称,但这似乎超出了此范围。
  2. 检查 EOF(文件结尾)
  3. 向文件添加内容
# Get the files via ssh and tar
files=$(ssh -n <user@server> $'tar -xf <tar-file> --wildcards \'*\' --to-command=$\'echo $TAR_FILENAME; cat /dev/stdin; echo \'[=11=]4\'\'')

# Keeps track of what state we're in (filename or content)
state="filename"
filename=""

# Each line is one of these:
#  - file's name
#  - file's data
#  - EOF
while read line; do
  if [[ $state == "filename" ]]; then
    filename=${line/*\//}
    touch $filename
    echo "Copying: $filename"
    state="content"
  elif [[ $state == "content" ]]; then
    # look for EOF (ctrl+d)
    if [[ $line == $'[=11=]4' ]]; then
      filename=""
      state="filename"
    else
      # append data to file
      echo $line >> <output-folder>/$filename
    fi
  fi
# Double quotes here are very important
done < <(echo -e "$files")

选择:tar + scp

如果上面的示例对于它正在做的事情来说看起来过于复杂,那确实是。一种更多接触磁盘并需要分离 ssh 连接的替代方法是将您需要的文件从 .tar 文件提取到一个文件夹,然后 scp 该文件夹返回您的工作站。

ssh -n <username>@<server> 'mkdir output/; tar -C output/ -xf <tar-file> --wildcards *.dat *.def'
scp -r <username>@<server>:output/ ./

细目

首先,我们将创建一个地方来保存我们输出的文件。如果您已经知道它们所在的文件夹,则可以跳过此步骤。

mkdir output/

然后,我们会将匹配的文件提取到我们创建的这个文件夹中(如果您不希望它们位于不同的文件夹中,请删除 -C output/ 选项)。

tar -C output/ -xf <tar-file> --wildcards *.dat *.def

最后,现在我们再次在我们的机器上 运行ning 命令,我们可以 运行 scp 重新连接到远程机器并拉回文件。

scp -r <username>@<server>:output/ ./