bash 如何通过 ssh 解压多个 tar 文件?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6208918/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I untar multiple tar files over ssh?
提问by CarpeNoctem
I am attempting to untar multiple tar files over ssh:
我正在尝试通过 ssh 解压多个 tar 文件:
ssh user@hostname "cat /dir/file*.tgz" | tar xvzf -
The above only works on the first file match on the remote server. The local (dest) server only receives one file. The wildcard has been verified to match multiple files though.
以上仅适用于远程服务器上的第一个文件匹配。本地(目标)服务器只接收一个文件。通配符已经过验证以匹配多个文件。
Is there another way to do this?
有没有其他方法可以做到这一点?
采纳答案by Pa?lo Ebermann
(Edit after first try didn't work:)
(第一次尝试后编辑不起作用:)
Another idea, avoiding multiple sshcalls and also scp(since this needs at least one roundtrip between each file):
另一个想法,避免多次ssh调用以及scp(因为这需要每个文件之间至少有一次往返):
ssh user@hostname 'tar cf - /dir/file*.tgz' | tar xf - --to-command='tar xzvf -'
We use one more tarcall on the server side to wrap all the files together, a second tarcall on the client side to unwrap them again, which will then be calling tar xzvfor each entry once. This works similar to the base64-answer from sehe, but will be more efficient since it does not blow up the files.
我们tar在服务器端再使用一次调用将所有文件包装在一起,tar在客户端使用第二次调用再次打开它们,然后tar xzv对每个条目调用一次。这与sehe的 base64-answer类似,但效率更高,因为它不会炸毁文件。
回答by sehe
mkdir /tmp/tars
scp 'user@hostname:/dir/file*.tgz' /tmp/tars/
foreach tarname in /tmp/tars/*.tgz; do tar xzvf "$tarname"; done
If you absolutely cannot store temp copies:
如果您绝对不能存储临时副本:
ssh user@hostname 'ls /dir/file*.tgz' | while read tarname;
do
ssh user@hostname "cat '/dir/$tarname'" | tar xzvf -
done
回答by bibliotechy
You could wrap this in a find call and then use the exec switch to iterate over each found file.
您可以将其包装在 find 调用中,然后使用 exec 开关遍历每个找到的文件。
ssh user@hostname 'find /path/to/dir -name "*.tar.gz" -exec tar xvf "{}" ";"'
Single ssh call, no need to write bash script.
单次 ssh 调用,无需编写 bash 脚本。
回答by sehe
CarpeNoctem inspired me to go even further and provide a one-stop solution that require only a single ssh connection and does all the stuff streaming.
CarpeNoctem 激励我走得更远,提供了一个一站式解决方案,它只需要一个 ssh 连接并完成所有内容的流式传输。
A tested proof concept (oneline formatted for readability):
经过测试的证明概念(为便于阅读而格式化的单行):
(echo '#!/bin/sh';
for a in /dir/file*.tgz
do
echo 'base64 -d <<"TARIMAGE" | tar xvzf -'
base64 "$a"
echo "TARIMAGE"
done) | ssh -C remote 'cd /targetdir && sh -'
Of course you'd actually want to reverse the roles of local and remote, in which case I'd recommend getting the script generation into a shell script instead:
当然,您实际上希望颠倒本地和远程的角色,在这种情况下,我建议将脚本生成改为 shell 脚本:
gen_script.sh, chmod +x
gen_script.sh, chmod +x
#!/bin/bash
echo '#!/bin/sh';
for a in /dir/file*.tgz
do
echo 'base64 -d <<"TARIMAGE" | tar xvzf -'
base64 "$a"
echo "TARIMAGE"
done
invocation
调用
scp gen_script.sh user@hostname:
ssh -C user@hostname /home/user/gen_script.sh | (cd targetdir && sh -)
Loose ends, thoughts:
松散的结局,想法:
- you can use uuencode, od, xxd, pgp or whatnot instead of base64
- you can enable compression on ssh (ssh -C) to further optimize bandwidth
- I made the targetdir/ step up myself to prevent accidents; you can let it off if you don't need it :)
- 您可以使用 uuencode、od、xxd、pgp 或诸如此类的代替 base64
- 您可以在 ssh (ssh -C) 上启用压缩以进一步优化带宽
- 我让 targetdir/ 自己加强以防止发生事故;如果你不需要它,你可以把它关掉:)
回答by Gilles 'SO- stop being evil'
It's easier to work with files than with commands. So rather than use the sshcommand to access remote hosts, and the tarcommand to access archives, use the SSHFSfilesystem to access files on remote hosts
使用文件比使用命令更容易。因此,与其使用ssh命令访问远程主机和tar访问档案的命令,不如使用SSHFS文件系统访问远程主机上的文件
mkdir hostname-dir.tmp
sshfs user@hostname:/dir hostname-dir.tmp
for a in hostname-dir.tmp/*.tgz; do tar xvf "$a"; done
fusermount -u hostname-dir.tmp
You can even go one step further and the AVFSto access archives as directories1. All brought to you by FUSE, a generic framework to access all kinds of things as files.
您甚至可以更进一步,使用AVFS将档案作为目录访问 1。所有这些都由FUSE带给您,FUSE是一个通用框架,可以将各种事物作为文件进行访问。
mountavfs
mkdir hostname-dir.tmp
sshfs user@hostname:/dir hostname-dir.tmp
for a in ~/.avfs$PWD/hostname-dir.tmp/*.tgz; do cp -Rp "$a#"/* .; done
fusermount -u hostname-dir.tmp
If your shell is zsh, that forloop can be replaced by a glob qualifier.
如果您的 shell 是 zsh,则该for循环可以替换为glob qualifier。
cp -Rp ~/.avfs$PWD/hostname-dir.tmp/*.tgz(e\''reply=($REPLY\#/*)'\') .
1 AVFS can also access remote files over SSH, but I don't think you can access remote archives that way: AVFS paths only have a single hop. So SSHFS is still necessary.
1 AVFS 也可以通过 SSH 访问远程文件,但我认为您不能通过这种方式访问远程档案:AVFS 路径只有一个跃点。所以SSHFS还是有必要的。

