我遇到了以下问题。我有一个文件夹,这个文件夹中大约有 100 个不同的文件夹,每个文件夹中大约有 500 个文件。我只想保留每个文件夹中的前 100 个文件。
我正在查看 while/loops,但似乎无法弄清楚。(我根本没有脚本技能)我已经看到并摆弄了一些脚本,但无法让它从每个文件夹中抓取前 100 个文件。
有没有更简单的方法可以做到这一点?
提前致谢!
答案1
假设你的文件名不包含空格或其他奇怪的字符,
您可以使用以下命令获取目录中按字母顺序排列的前 100 个文件:
find . -maxdepth 1 -type f -print | sort |head -n 100
但是,要获取所有其他文件(您想要“不保留”的文件):
find . -maxdepth 1 -type f -print | sort |tail -n +101
然后,*
用文件夹列表替换,执行以下操作:
for f in * ; do
cd $f
# to delete all but the first 100
find . -maxdepth 1 -type f -print | sort |tail -n +101 | xargs rm
# or, to copy them elsewhere
mkdir ../new_$f
find . -maxdepth 1 -type f -print | sort |head -n 100 | \
xargs cp --target-directory=../new_$f
# remember to undo initial cd $f
cd ..
done
答案2
如果您有zsh
,使用其 glob 限定符可以轻松实现这种操作。*
默认情况下,匹配所有非隐藏文件(包括目录),zsh
允许您使用 glob*(.[1,100])
引用前 100 个纯文本文件(按名称按词汇顺序排序)或*(.[101,-1])
匹配第 100 个之后的所有纯文本文件。例如,您可以这样做
for d in *(/); do echo rm -- "$d"/*(.[101,-1]); done
(回显)从当前目录的每个子目录中删除除(词汇上)前 100 个文件之外的所有文件。
如果结果参数列表太长,你可以将上述内容修改为
for d in *(/); do print -rN -- "$d"/*(.[101,-1]) | xargs -r0 echo rm -- ; done
echo
只有在您绝对确定它与目标文件匹配时才删除。
要复制前 100 个文件而不是删除所有其余文件,请
for d in *(/); do echo cp -t path/to/dest -- "$d"/*(.[1,100]); done
或者如果参数列表太长
for d in *(/); do
print -rN -- "$d"/*(.[1,101]) | xargs -r0 echo cp -t path/to/dest/ --
done
为了在 bash 中以对任何合法文件名安全的方式实现几乎相同的功能,您可以使用set
和shift
内置命令:
for d in */; do set -- "$d"*; shift 100; echo rm -- "$@"; done
或者如果参数列表太长
for d in */; do
set -- "$d"*; shift 100; printf -- '%s\0' "$@" | xargs -r0 echo rm --
done
请注意,这里没有与 zsh(.)
纯文件限定符等效的 - 如果有目录,它将匹配并尝试删除目录。