焦油的有趣用法......但是发生了什么?

fog*_*gus 10 bash scripting tar

我在同事的Bash脚本中看到了tar的以下有趣用法:

`tar cf - * | (cd <dest> ; tar xf - )`
Run Code Online (Sandbox Code Playgroud)

显然它的工作方式与rsync -av相似,但速度更快.问题出现了,怎么样?

-m


编辑:任何人都可以解释为什么这个解决方案优于以下?

cp -rfp * dest
Run Code Online (Sandbox Code Playgroud)

前者更快吗?

tva*_*son 12

它将存档写入标准输出,然后将其传送到子进程(由括号括起),该子进程将更改为其他目录并从标准输入读取/提取.这就是f论证后的破折号字符的含义.它基本上将当前目录的所有可见文件和子目录复制到另一个目录.


Ala*_*air 9

关于复制目录层次结构的cp和tar之间的区别,可以进行一个简单的实验来显示差异:

alastair box:~/hack/cptest [1134]% mkdir src
alastair box:~/hack/cptest [1135]% cd src
alastair box:~/hack/cptest/src [1136]% touch foo
alastair box:~/hack/cptest/src [1137]% ln -s foo foo-s
alastair box:~/hack/cptest/src [1138]% ln foo foo-h
alastair box:~/hack/cptest/src [1139]% ls -a
total 0
-rw-r--r--  2 alastair alastair    0 Nov 25 14:59 foo
-rw-r--r--  2 alastair alastair    0 Nov 25 14:59 foo-h
lrwxrwxrwx  1 alastair alastair    3 Nov 25 14:59 foo-s -> foo
alastair box:~/hack/cptest/src [1142]% mkdir ../cpdest
alastair box:~/hack/cptest/src [1143]% cp -rfp * ../cpdest
alastair box:~/hack/cptest/src [1144]% mkdir ../tardest
alastair box:~/hack/cptest/src [1145]% tar cf - * | (cd ../tardest ; tar xf - )
alastair box:~/hack/cptest/src [1146]% cd ..
alastair box:~/hack/cptest [1147]% ls -l cpdest
total 0
-rw-r--r--  1 alastair alastair    0 Nov 25 14:59 foo
-rw-r--r--  1 alastair alastair    0 Nov 25 14:59 foo-h
lrwxrwxrwx  1 alastair alastair    3 Nov 25 15:00 foo-s -> foo
alastair box:~/hack/cptest [1148]% ls -l tardest
total 0
-rw-r--r--  2 alastair alastair    0 Nov 25 14:59 foo
-rw-r--r--  2 alastair alastair    0 Nov 25 14:59 foo-h
lrwxrwxrwx  1 alastair alastair    3 Nov 25 15:00 foo-s -> foo
Run Code Online (Sandbox Code Playgroud)

不同之处在于硬链接文件.注意如何单独复制硬链接文件cp和与之一起单独复制tar.为了使差异更明显,请查看每个的inode:

alastair box:~/hack/cptest [1149]% ls -i cpdest
24690722 foo  24690723 foo-h  24690724 foo-s
alastair box:~/hack/cptest [1150]% ls -i tardest
24690801 foo  24690801 foo-h  24690802 foo-s
Run Code Online (Sandbox Code Playgroud)

可能还有其他理由喜欢tar,但这是一个很大的原因,至少如果你有广泛的硬链接文件.

  • 你想要做的是将"`--archive`"传递给`cp`,这将解决它.当然假设GNU`cp'. (3认同)

小智 5

对于包含25,000个空文件的目录:

$ time { tar -cf - * | (cd ../bar; tar -xf - ); }
real    0m4.209s
user    0m0.724s
sys 0m3.380s

$ time { cp * ../baz/; }
real    0m18.727s
user    0m0.644s
sys 0m7.127s

对于每个包含4个文件1073741824字节(1GB)的目录

$ time { tar -cf - * | (cd ../bar; tar -xf - ); }
real    3m44.007s
user    0m3.390s
sys 0m25.644s

$ time { cp * ../baz/; }
real    3m11.197s
user    0m0.023s
sys 0m9.576s

我猜这种现象是高度依赖于文件系统的.如果我是对的,你会发现专门研究众多小文件的文件系统(如reiserfs 3.6)和处理大文件的文件系统之间存在巨大差异.

(我在HFS +上运行了上述测试.)