在bash中折叠嵌套目录

在bash中折叠嵌套目录,bash,Bash,解压文件后,我通常会得到一个目录,其中只包含另一个目录(例如,mkdir foo;cd foo;tar xzf~/bar.tgz可能只在foo中生成一个bar目录)。我想编写一个脚本,将其折叠到一个目录中,但是如果嵌套目录中有点文件,则会使事情变得有点复杂 下面是一个简单的实现: mv -i $1/* $1/.* . rmdir $1 这里唯一的问题是,它还将尝试移动和。并请求覆盖。/。?(是/否[n])。我可以通过依次检查每个文件来解决此问题: IFS=$'\n' for file in $

解压文件后,我通常会得到一个目录,其中只包含另一个目录(例如,
mkdir foo;cd foo;tar xzf~/bar.tgz
可能只在
foo
中生成一个
bar
目录)。我想编写一个脚本,将其折叠到一个目录中,但是如果嵌套目录中有点文件,则会使事情变得有点复杂

下面是一个简单的实现:

mv -i $1/* $1/.* .
rmdir $1
这里唯一的问题是,它还将尝试移动
并请求
覆盖。/。?(是/否[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和./bar是相同的


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

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

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

首先,考虑许多<代码> TAR 实现提供了<代码>条状组件选项,允许您删除第一个路径。不确定是否有第一条路径

tar -tf yourball.tar | awk -F/ '!s[$1]++{print$1}'
将向您显示所有第一级内容。如果只有一个目录,那么

tar --strip-components=1 -tf yourball.tar
将tar中该目录的内容提取到当前目录中

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

foo/bar/stuff
foo/bar/.otherstuff
你能行

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

--strip components
功能不是POSIX规范中针对
tar
的一部分,但它在通用GNU和OSX/BSD实现中都有。

虽然dotlob解决方案更干净,但是
查找目录-type f
方法没有任何错误,除非您在读取时应该使用
。。。。完成<我还想移动嵌套目录,因此我认为仅
find dir-type f
是不够的,而且
find dir-type d
存在匹配
dir
本身的问题。如果您只是将给定
dir
下的所有文件移动到当前目录,并在完成后删除
dir
,这不应该是个问题。如果您需要保留一些嵌套的
目录
,那么是的,移动和第二次调用
查找目录-type d.
可能是正确的。