我正在编写一个bash脚本来进行部署tarball,脚本必须在OSX和Linux上运行。
我有一个如下所示的目录结构,在bash脚本中我需要tar除./foo
之外的内容,但包括./baz/foo
$ find .
.
./bar
./baz
./baz/foo
./foo
简单!通常我会通过将--exclude='./foo'
传递给tar命令来执行此操作,但我发现--exclude=pattern
的行为在OSX和CentOS中是不同的。
我的问题是,如何最好地克服这个问题?如何使两个环境的行为相同或至少检测到所需的更改?
或者,任何人都可以为他们确认这种行为(OSX 10.11),以便我知道我没有一些奇怪的环境吗?
CentOS按预期工作:
$ tar zcfv ../test.tar.gz --exclude='./foo' .
./
./bar/
./baz/
./baz/foo/
OSX表现不同:
$ tar zcfv ../test.tar.gz --exclude='./foo' .
a .
a ./bar
a ./baz
经过几个小时的阅读文档,我发现没有什么可以解释这种不同的行为,但通过反复试验,我发现使用插入符表示模式的开始在OSX上有效。
OSX的修复程序(使用插入符号):
$ tar zcfv ../test.tar.gz --exclude='^./foo' .
a .
a ./bar
a ./baz
a ./baz/foo
但是在CentOS上不起作用:
$ tar zcfv ../test.tar.gz --exclude='^./foo' .
./
./bar/
./foo/
./baz/
./baz/foo/
最后,我注意到OSX附带了bsdtar而不是GNU tar,所以这是问题的根源吗?
OSX:
$ tar --version
bsdtar 2.8.3 - libarchive 2.8.3
CentOS的:
$ tar --version
tar (GNU tar) 1.23
答案 0 :(得分:1)
感谢您的评论。在--exclude=pattern
的实现中,这似乎是bsdtar和GNU tar之间的根本区别,并且没有办法让它们表现相同。
由于我可以控制操作系统环境,我可接受的解决方法是使用brew在OSX上安装GNU tar(感谢@Seer)。然后我在我的脚本中使用以下内容来检测安装的tar是否为GNU,如果没有则回退到gtar。如果没有安装gtar,它将中止。
# OSX uses bsdtar which causes problems with --exclude=pattern
# so force use of gtar if non-GNU tar detected
tar --version | grep -q 'gnu'
if [ $? -eq 0 ]
then
echo "Detected GNU tar - using tar"
TAR_BIN=`command -v tar 2>&1` || { echo >&2 "I require tar but it is not installed. Aborting."; exit 1; }
else
echo "Detected non-GNU tar - using gtar"
TAR_BIN=`command -v gtar 2>&1` || { echo >&2 "I require gtar but it is not installed. Aborting."; exit 1; }
fi
# this will now work consistently as GNU tar is always used
$TAR_BIN zcfv ../test.tar.gz --exclude='./foo' .
注意:CentOS至少实际上是别名gtar到tar,所以假设使用gtar命令可能是安全的,但我更喜欢上面的方法。