2015-05-13 58 views
2

解压缩文件后,经常会出现一个目录,其中只包含另一个目录(例如,mkdir foo; cd foo; tar xzf ~/bar.tgz可能在foo中除bar目录外都会产生任何内容)。我想编写一个脚本将其折叠到一个目录中,但是如果嵌套目录中有点文件,它会使事情变得复杂一点。在bash中折叠嵌套的目录

这里有一个天真的实现:

mv -i $1/* $1/.* . 
rmdir $1 

这里唯一的问题是,它还会尝试移动...并要求overwrite ./.? (y/n [n])。我可以通过依次检查每个文件来解决此问题:

IFS=$'\n' 
for file in $1/* $1/.*; do 
    if [ "$file" != "$1/." ] && [ "$file" != "$1/.." ]; then 
     mv -i $file . 
    fi 
done 
rmdir $1 

但是,这似乎是一个不雅的解决方法。我试图用find清洁方法:

for file in $(find $1); do 
    mv -i $file . 
done 
rmdir $1 

find $1也会给$1结果,其中给出了mv: bar and ./bar are identical错误。

虽然第二种方法似乎有效,但是有没有更好的方法来实现这一点?

+0

尽管dotglob解决方案比较干净,但find'dir -type f'方法没有什么问题,除了您应该使用'while read .... done <<(find ...)'循环来处理它。 –

+0

我也想移动嵌套的目录,所以我不认为'单独找到dir -type f'就足够了,'find dir -type d'有匹配'dir'本身的问题。 –

+0

如果您只是将给定的'dir'下的所有文件移动到当前位置并在完成时移除'dir',那就不应该成为问题。如果你需要保留一些嵌套的'dirs',那么是的,移动和第二次调用'find dir -type d ...'可能是有序的。 –

回答

3

打开dotglob shell选项,它允许您的模式匹配以.开头的文件。

shopt -s dotglob 
mv -i "$1"/* . 
rmdir "$1" 
1

首先,考虑到许多tar的实现提供了--strip-components选项,允许你剥掉那第一个路径。不确定是否有第一条路?

tar -tf yourball.tar | awk -F/ '!s[$1]++{print$1}' 

会告诉你所有的第一级内容。如果只有一个目录,然后

tar --strip-components=1 -tf yourball.tar 

将提取内容焦油该目录的到当前目录。

这就是你完全可以避免这个问题的方法。但它也是解决你眼前的问题。已经提取文件了,所以你必须

foo/bar/stuff 
foo/bar/.otherstuff 

你可以做

tar -cf- foo | tar --strip-components=2 -C final_destination -xf- 

--strip-components功能不是tar POSIX规范的一部分,但它是在普通GNU和OSX /两BSD实现。