![如何按计数将文件移动到子目录中?](https://linux22.com/image/7692/%E5%A6%82%E4%BD%95%E6%8C%89%E8%AE%A1%E6%95%B0%E5%B0%86%E6%96%87%E4%BB%B6%E7%A7%BB%E5%8A%A8%E5%88%B0%E5%AD%90%E7%9B%AE%E5%BD%95%E4%B8%AD%EF%BC%9F%20.png)
我的目录中有大约 100,000 个文件。正如您可以想象的那样,这不是理想的情况,我想将目录拆分为子目录。但文件名并不能让我根据名称或其他内容将它们放入子目录中,因此我想创建 10 个目录,并在每个目录中放入大约 1000 个文件。有没有一个简单的 bash 命令或循环可以做到这一点?
答案1
尝试:
n=0; for f in *; do d="subdir$((n++ / 1000))"; mkdir -p "$d"; mv -- "$f" "$d/$f"; done
n
跟踪已移动的文件数量。在数千个批次中,每个文件都被分配到名为 的子目录subdir$((n++ / 1000))
。 (您可以根据需要调整命名。)如果尚未创建,mkdir -p "$d"
请创建该子目录。 mv -- "$f" "$d/$f"
将文件传输到该子目录。
答案2
鉴于源目录中的文件数量较多,建议的解决方案可能需要几分钟的时间。
如果您不想等待,您可能需要考虑一种不会为每次移动生成进程的解决方案。
要批量移动,您可以利用以下事实:cpio
with--pass-through
和--link
有点像移动一样 - 如果源和目标位于同一文件系统上,操作将很快,否则将创建整个副本。
与 不同的是mv
,将为每个源文件留下一个硬链接,但如果操作成功,稍后cpio -lpd
可以轻松将其全部删除:rm -r
目录分割器的实现可能类似于:
split_dir()(
local src=$1 nbatches=$2 dest=$3
local tmpd=
trap 'rm -rf "$tmpd"' EXIT
tmpd="$(mktemp -d "$tmpd")"
find -type f "$src" > "$tmpd/files"
local nfiles=$(wc -l < "$tmpd/files")
local batchsz=$((nfiles/nbatches))
( cd "$tmpd"; split -l "$batchsz" -d files )
local i
for((i=0;i<nbatches;i++)); do
mkdir -p "$dest/$i"
< x$i cpio -pdl "$dest/$i"
done
)