将多个文件夹中的前 100 个文件复制到一个文件夹(或删除其余文件)

将多个文件夹中的前 100 个文件复制到一个文件夹(或删除其余文件)

我遇到了以下问题。我有一个文件夹,这个文件夹中大约有 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 中以对任何合法文件名安全的方式实现几乎相同的功能,您可以使用setshift内置命令:

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(.)纯文件限定符等效的 - 如果有目录,它将匹配并尝试删除目录。

相关内容