Answers:
您可以使用GNU find
和GNU 来做到这一点mv
:
find /dir1 -mindepth 2 -type f -exec mv -t /dir1 -i '{}' +
基本上,如果find
遍历整个目录树并且对于-type f
不在顶级目录(-mindepth 2
)中的每个文件()进行操作,它将运行a mv
来将其移动到所需的目录(-exec mv … +
)。该-t
参数mv
可以让你先指定目标目录,这是必须的,因为+
形式-exec
将所有在命令结束的源位置。该-i
品牌mv
覆盖任何重复之前询问; 您可以替代-f
不要求(或-n
不要求或覆盖)而覆盖它们。
正如Stephane Chazelas指出的那样,以上内容仅适用于GNU工具(Linux上是标准工具,但其他大多数系统却不适用)。以下内容会稍微慢一些(因为它会被mv
多次调用),但是更通用一些:
find /dir1 -mindepth 2 -type f -exec mv -i '{}' /dir1 ';'
-exec +
,使其不会执行大量的处理mv
mv
需要将目的地作为最后一个参数,但+会将源作为最后一个参数。查找甚至都不会接受将其更改为(find: missing argument to `-exec'
)的语法
mv
有一个-t
可以使用的,所以我将其更改为该名称。
find
默认情况下打印隐藏的(点)文件。深度与您要查找的目录有关。
find ./dir -mindepth 2 -type f -exec mv -f '{}' ./dir ';'
如果覆盖重复项
在zsh中:
mv dir1/*/**/*(.D) dir1
**/
递归遍历子目录。该水珠预选赛 .
只有符合规则的文件,并D
确保点文件包含(默认情况下,文件的名字开始与一个.
被排除通配符匹配)。在事后清理目前空目录,运行rmdir dir1/**/*(/Dod)
- /
限制了目录,od
第一批订单的深度匹配,从而去除dir1/dir2/dir3
之前dir1/dir2
。
如果文件名的总长度很大,则可能会遇到命令行长度的限制。Zsh具有内置插件,mv
并且rmdir
不受此限制的影响:运行zmodload zsh/files
以启用它们。
仅使用POSIX工具:
find dir1 -type f -exec mv {} dir1 \;
find dir1 -depth -exec rmdir {} \;
或(速度更快,因为它不必为每个文件运行单独的进程)
find dir1 -type f -exec sh -c 'mv "$@" dir1' _ {} +
find dir1 -depth -exec rmdir {} +
尝试这样做:
cp /dir1/dir2/file{1,2} /another/place
或file[0-9]*
子目录中匹配的每个文件:
cp /dir1/dir2/file[0-9]* /another/place
{}
在实际问题中我必须使用许多文件。
我写了两个可以一起使用的函数,它们可以通过添加-maxdepth $VAL
参数来限制目录级别。
# This scripts flattens the file directory
# Run this script with a folder as parameter:
# $ path/to/script path/to/folder
#!/bin/bash
rmEmptyDirs(){
local DIR="$1"
for dir in "$DIR"/*/
do
[ -d "${dir}" ] || continue # if not a directory, skip
dir=${dir%*/}
if [ "$(ls -A "$dir")" ]; then
rmEmptyDirs "$dir"
else
rmdir "$dir"
fi
done
if [ "$(ls -A "$DIR")" ]; then
rmEmptyDirs "$DIR"
fi
}
flattenDir(){
local DIR="$1"
find "$DIR" -mindepth 2 -type f -exec mv -i '{}' "$DIR" ';'
}
read -p "Do you wish to flatten folder: ${1}? " -n 1 -r
echo # (optional) move to a new line
if [[ $REPLY =~ ^[Yy]$ ]]
then
flattenDir "$1" &
rmEmptyDirs "$1" &
echo "Done";
fi
由于我有一个平整包含同名文件的目录的用例,因此扩展了该问题的流行答案。
dir1/
├── dir2
│ └── file
└── dir3
└── file
在这种情况下,传递给-i
(--interactive
)选项mv
将不会产生使目录结构变平和处理名称冲突的预期结果。因此,只需将其替换为--backup=t
(等效于--backup=numbered
)。有关-b
(--backup
)选项的更多文档,请访问https://www.gnu.org/software/coreutils/manual/coreutils.html#Backup-options。
导致:
find dir1/ -mindepth 2 -type f -exec mv -t dir1/ --backup=t '{}' +
产生:
dir1/
├── dir2
├── dir3
├── file
└── file.~1~