将所有最低级子目录(但不包括中级目录或文件)移动到目标目录

将所有最低级子目录(但不包括中级目录或文件)移动到目标目录

假设我有一个source/目录,它有许多子目录。有些子目录下又有子子目录,有些子子目录下又有子子子目录,等等。

我要做的是递归地查找所有最低级子目录(没有任何进一步子目录的子目录)source/并将它们移动到新的目标目录。

例如,假设原文source/如下:

/source/dir1               --Subdirectory without sub-subdirectory
/source/dir2               --Subdirectory with sub-subdirectory
/source/dir2/dir2.a        --Sub-subdirectory without sub-sub-subdirectory
/source/dir2/dir2.b        --Sub-subdirectory without sub-sub-subdirectory

那么操作之后target目录应该是这样的:

/target/dir1
/target/dir2.a
/target/dir2.b

有没有办法用终端命令来做到这一点?

答案1

假设您所在的文件系统的叶目录恰好有 2 个硬链接,则您可以像这样组合使用 find、xargs 和 mv:

$ find . -type d -printf "%n %p\n"                   \
    | grep '^2 '                                     \
    | perl -ne 'chomp; s/[0-9]+\s+//; print "$_\0";' \
    | xargs -0 -I'{}' mv -v '{}' /target/

这使用 find 来仅查找目录并打印这些目录具有的硬链接数量。

然后我们使用 grep 删除任何不是“叶子”的内容。

接下来我们使用 Perl 来切断硬链接数,并打印以 分隔的文件\0

最后,让我们使用带有-0标志的 xargs 将找到的目录移动到目标目录中。

对于包含空格的文件,使用空值 ( \0) 而不是换行符或空格非常重要。如果您的目录名称保证不包含空格,那么您可以稍微简化一下。

$ find . -type d -printf "%n %p\n" | grep '2 ' | cut -d " " -f 2 | xargs -I'{}' mv -v '{}' /target/

但谨慎一点总比后悔好。

答案2

一种方法可能是使用find来获取每个目录,并将结果传递给第二个目录,并且仅当第二个目录返回给定目录下的任何目录find时才执行移动,例如find

while read -rd $'\0' dir; do 
    [[ -z $(find "$dir" -mindepth 1 -type d) ]] && mv -t path/to/target "$dir"
done < <(find -depth -type d -print0)

或者

find -depth -type d -execdir \
bash -c '[[ -z $(find "$0" -mindepth 1 -type d) ]] && mv -t path/to/target "$0"' {} +

例如

$ tree .
.
├── dir1
└── dir2
    ├── dir2.a
    └── dir2.b

然后

$ while read -rd $'\0' dir; do [[ -z $(find "$dir" -mindepth 1 -type d) ]] && echo mv -t path/to/target "$dir"; done < <(find -depth -type d -print0)
mv -t path/to/target ./dir1
mv -t path/to/target ./dir2/dir2.b
mv -t path/to/target ./dir2/dir2.a

相关内容