简体   繁体   English

我如何循环浏览特定数量的文件夹

[英]How do i loop through certain number of folders

I am trying to loop through a folder that has 744 sub directories.我正在尝试遍历具有 744 个子目录的文件夹。 How do i loop through only certain number of folders.我如何只循环浏览特定数量的文件夹。 Since i have 744 sub directories i would split this into half and loop through first 372 directories and then later on loop through rest of the 372 directories.由于我有 744 个子目录,我会将其分成两半并循环遍历前 372 个目录,然后循环遍历其余 372 个目录。 I want to make sure i don't copy directories multiple times.我想确保我不会多次复制目录。 Below is what i tried doing but i want to know what would be the effective way of doing this to avoid duplication.以下是我尝试做的,但我想知道这样做以避免重复的有效方法是什么。

for d in `ls -tr|tail -372`
do
echo $d
done

Since my xargs answer didn't receive any feedback, here's another approach.由于我的xargs回答没有收到任何反馈,这是另一种方法。

printf "%s\n" */ |
awk 'BEGIN { n=1; OFS="\t"
        split("first:second:third", destination, /:/) }
    (i++ % 372)=0 { ++n }
    { print destination[n], $0 }'

This will add a field in front of each directory name, which you can use to process the results further.这将在每个目录名称前添加一个字段,您可以使用该字段进一步处理结果。 Sample output:示例输出:

first   directory1/
first   directory2/
first   directory3/
:
first   directory372/
second  directory373/
second  directory374/
:
second  directory743/
second  directory744/

So the field value third from the Awk script is never used, but I put it in anyway to demonstrate that this could easily be extended to do three-way partitions, or four-way or what have you.所以从未使用过 Awk 脚本中的third字段值,但我还是把它放在里面是为了证明这可以很容易地扩展到做三向分区、四向分区或你有什么。

You would use this eg by piping to您可以通过管道来使用它

while IFS= read -r dest dir; do
    echo mv "dir" "$dest"
done

Unlike the xargs -0 answer, this is not robust against arbitrary file names;xargs -0答案不同,这对任意文件名不可靠; in particular, directory names which contain newlines will not work correctly.特别是,包含换行符的目录名称将无法正常工作。

Actually a much better solution would be to split the files the other way -- ie for a two-way partition, print first on every other line, and second on every other.其实一个更好的解决办法是分割的文件的其他方式-即一个双向的分区,打印first每隔一行,并且second每隔。 Then you don't have to hard-code the number of items, just the number of partitions.然后您不必对项目数进行硬编码,只需对分区数进行硬编码。

printf "%s\n" */ |
awk 'BEGIN { OFS="\t"
        n = split("ernie:bert", host, /:/) }
    { print host[1+((NR-1)% n)], $0 }' |
while IFS= read -r server dir; do
    mkdir -p "$server"
    mv "$dir" "$server/"
done

Regardless of the number of directories, this splits them evenly into the directories ernie and bert , on the optimistic assumption that you (too) might have named your file servers after Sesame Street characters.无论目录的数量如何,这都会将它们均匀地分成目录erniebert ,乐观地假设您(也)可能已经以芝麻街字符命名您的文件服务器。

If you want to scp the directories instead of mv them, grouping them by server name would be a lot more efficient;如果你想scp目录而不是mv它们,按服务器名称对它们进行分组会更有效率; but a simple sort takes care of that if necessary.但如果有必要,一个简单的sort会照顾到这一点。 (That's not the only reason we print the destination before each file name; it's also useful because then we don't have to worry that the directory names could contain our field separator.) (这不是我们在每个文件名之前打印目标的唯一原因;这也很有用,因为这样我们就不必担心目录名可能包含我们的字段分隔符。)

You can use xargs but this requires the 372 directory names to fit in one invocation (ie the directory names combined must not exceed ARG_MAX ).您可以使用xargs但这需要 372 个目录名称以适合一次调用(即组合的目录名称不得超过ARG_MAX )。

printf '%s\0' */ |
xargs -n 372 -r -0 sh -c '
    d=dest$$; mkdir "$d"; cp "$@" "$d"' _

This will generate a unique new directory with the prefix dest and a number for each batch of directories it copies.这将生成一个带有前缀dest的唯一新目录,并为它复制的每批目录生成一个编号。 There are probably better ways to split the files (and calling sh from xargs is not exactly a newbie-friendly answer) but maybe this should at least give you some ideas.可能有更好的方法来分割文件(并且从xargs调用sh并不是一个对新手友好的答案),但也许这至少应该给你一些想法。

In some more detail, xargs -n 372 limits the number of arguments that get processed in one go, and the command you pass to xargs could be something a lot simpler;更详细地说, xargs -n 372限制了一次性处理的参数数量,您传递给xargs的命令可能会简单得多; xargs -n 372 cp -t fnord would copy first 372 directories to fnord , then another 372; xargs -n 372 cp -t fnord会将前 372 个目录复制到fnord ,然后再复制 372 个; but in order for this to be actualy useful, we want the destination directory to change each time we call xargs , and so I put in a simple script which does that.但是为了使这真正有用,我们希望每次调用xargs时都更改目标目录,因此我放入了一个简单的脚本来执行此操作。

You also need to understand that 372 is a maximum, and if the directory names are really long, xargs could decide that it needs to pass fewer directories in order to not cross the "argument list too long" limit.您还需要了解 372 是最大值,如果目录名称真的很长, xargs可以决定它需要传递更少的目录,以免超过“参数列表太长”的限制。 But for your use case, on any remotely modern system, we are probably far below that limit anyway.但是对于您的用例,在任何远程现代系统上,无论如何我们都可能远低于该限制。

xargs -0 and cp -t are GNU extensions, ie they should work on Linux out of the box, and you can install them on most other platforms; xargs -0cp -t是 GNU 扩展,即它们应该在 Linux 上开箱即用,并且您可以在大多数其他平台上安装它们; if you really need to support something like Solaris without installing external tools, that's going to be slightly more challenging.如果您真的需要在不安装外部工具的情况下支持 Solaris 之类的东西,那将更具挑战性。


Addendum: Here's a xargs implementation of the ernie & bert part of the Awk answer:附录:这是 Awk 答案中ernie & bert部分的xargs实现:

printf "%s\0" */ |
xargs -r -0 -n 2 sh -c '
    mkdir -p ernie bert
    mv "$1" ernie
    mv "$2" bert' _

There will be an ugly but harmless error message for the last item if you have an uneven number of input directories.如果您的输入目录数量奇数,那么最后一项会出现丑陋但无害的错误消息。 There are obvious but inelegant ways to fix that, or elegant but obscure ones;有明显但不优雅的方法来解决这个问题,或者优雅但晦涩的方法; but I prefer to keep this plain for now.但我现在更喜欢保持简单。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM