![如何将所有目录移动到特定大小以下?](https://linux22.com/image/225242/%E5%A6%82%E4%BD%95%E5%B0%86%E6%89%80%E6%9C%89%E7%9B%AE%E5%BD%95%E7%A7%BB%E5%8A%A8%E5%88%B0%E7%89%B9%E5%AE%9A%E5%A4%A7%E5%B0%8F%E4%BB%A5%E4%B8%8B%EF%BC%9F.png)
我想移动当前目录中小于特定大小的所有目录
在这里,我做出了选择:
for dir in *
do
if [[ $(du -s "$dir" | awk '{print $1}') -le 50000 ]]
then
ls -l "$dir"
fi
done
我现在认为我应该使用 dirname 来获取目录,但不知何故,无论我做什么它都会抱怨;)
我们有一个巧妙的方法来做到这一点吗?;)
答案1
假设您已经正确完成了跑腿工作, mv 命令的位置:将位于 ls -l "$dir" 之后和 "fi" 之前。
例如: mv $dir /where/you/want/it/re located
如果目录名称中包含“”(或与此相关的其他特殊字符),则可能会出现一个问题。如果遇到此类问题,您可以进一步咨询:转义变量以用作另一个脚本的内容线程的灵感。
答案2
我会和
find . -maxdepth 1 -type d | grep -v ^\\.$ | xargs -n 1 du -s | while read size name ; do if [ $size -le 50000 ] ; then mv "$name" /path/to/target/ ; fi done
查找当前目录中大小小于 50000 的每个目录并将其移动到目标目录中。
答案3
以下是移动同一级别中小于 1000 KB 的所有文件夹的示例:
find . -mindepth 1 -maxdepth 1 -type d -exec bash -c 'if [ $(du -d0 {} | cut -f1) -lt 1000 ];then mv {} SOMEWHERE;fi' \;
答案4
为了能够在 GNU 系统上处理任意目录名称,您可以这样做:
du --block-size=1 -l0d1 |
perl -0 -lne '
print $2 if /^(\d+)\t(.*)/s && $2 ne "." && $1 < 50000 * 1024' |
xargs -r0 mv -vt /destination/directory --
请注意,du
默认块大小为 512,但du
出于某种原因 GNU 决定将其更改为 1024。但是,当$POSIXLY_CORRECT
它处于环境中时,它会发生变化,并且也可以通过DU_BLOCK_SIZE
,BLOCK_SIZE
和BLOCKSIZE
环境变量进行更改。
所以最好在命令行上明确指定它。当块大小为 1 时,您可以以字节精度指定磁盘使用情况,从而更容易进行后处理²。
使用-d1
,与 相同--max-depth=1
,我们可以获得当前工作目录的每个子目录和当前工作目录本身的磁盘使用情况(不幸的是没有--min-depth
)。这避免了在du
每个目录上运行,但也意味着它正在计算当前目录中我们不需要的文件的大小,我们需要用$2 ne "."
in丢弃这些文件perl
。与执行操作相比du -- */
,这样做的优点是不跳过隐藏目录,也不处理目录的符号链接。
这意味着我们需要-l
aka--count-links
来计算在这些目录的递归下降中找到的文件的每个硬链接,否则如果在子目录之一中找到给定文件的硬链接,则不会计算到该文件的其他硬链接在任何其他目录中。请注意,这也意味着硬链接到给定文件在同一个子目录下du -s
也都被计算在内,因此您最终可能会得到与在单个目录上使用时不同的值。
因此,如果您的目录树状结构可能包含硬链接,则最好为du
每个目录调用一个硬链接,以确保它们彼此独立地进行计数。
find . ! -name . -prune -type d -printf '%P\0' |
xargs -r0 -n1 du --block-size=1 -0s -- |
perl -0 -lne '
print $2 if /^(\d+)\t(.*)/s && $2 ne "." && $1 < 50000 * 1024' |
xargs -r0 mv -vt /destination/directory --
要便携式地做类似的事情(忽略玩具盒du
1),可以这样做:
for dir in .* *; do
[ "$dir" = . ] || [ "$dir" = .. ] && continue
[ -d "$dir" ] || continue
[ -L "$dir" ] && continue
du_output=$(
LC_ALL=C POSIXLY_CORRECT=1 BLOCK_SIZE=512 BLOCKSIZE=512 DU_BLOCK_SIZE=512 du -s -- "$dir"
) || continue # don't take any decision if du fails for that dir
LC_ALL=C awk -- '
BEGIN {$0 = ARGV[1]; exit !($1 * 512 < 50000 * 1024)}
' "$du_output" || continue
mv -- "$dir" /destination/directory
done
(未经测试)。
与第一种方法总共运行 4 个命令(如果mv
目录数量较多,则需要运行多次,则需要运行更多命令)相比,该方法最多运行 7 个命令每个文件所以效率会低很多。
1 其他一些主要针对 Linux 的实现(例如 busybox 和 toybox)选择与 GNU 保持一致,du
而不是与这方面的历史实践和标准保持一致。最糟糕的是“toybox”(例如在 Android 上找到的),它不支持POSIXLY_CORRECT
、BLOCKSIZE
、BLOCK_SIZE
nor中的任何一个,DU_BLOCK_SIZE
并且具有-b
(byte)、-k
(kibibyte,默认值)、-K
(512)、-m
(mebibyte) 选项,这意味着不可能du
在便携式时尚(如果需要考虑该实现)。
² 虽然增加了整数溢出的风险。 512 通常是最小空间分配单位,因此作为磁盘使用的默认单位是有意义的。