【问题标题】:Using find and exec to create directories and then work with relative path to that directory使用 find 和 exec 创建目录,然后使用该目录的相对路径
【发布时间】:2012-10-22 11:46:18
【问题描述】:

我在结构化文件夹中有一堆 .emlx Apple Mail 文件,我想将它们导入 Apple Mail。我知道我可以手动执行此操作,方法是将文件夹重命名为 folder.mbox,然后将 .emlx 文件放在名为“Messages”的嵌套文件夹中。

我有数百个这样的文件夹,所以我尝试使用 bash 而不是手动完成。

我可以这样设置基本结构:

find /path/to/folders/* -type d -exec mv {} {}.mbox \; -exec mkdir {}.mbox/Messages \;

但我无法弄清楚如何将 .emlx 文件移动到新创建的子文件夹中。我试过这个:

find /path/to/folders/ -name \*.emlx -print0 | xargs -0 -I {} mv {} ./Messages/

...我认为这是一个长镜头,但肯定有一些方法可以处理 find 相对于每个结果的路径生成的文件列表。

【问题讨论】:

  • 示例路径会很有帮助ö

标签: macos bash find xargs


【解决方案1】:

怎么样:

find /path/to/folders/* -type d \
        -exec mv {} {}.mbox \; \
        -exec mkdir {}.mbox/Messages \; \
        -exec sh -c "mv {}.mbox/*.emlx {}.mbox/Messages" \;

这在我的测试环境中对我有用 — 就它给了我预期的结果而言 — 但它也收到了来自 find 的警告,我不喜欢(尤其是因为我不太确定为什么它会发出警告)。

因此,我将创建一个名为fixmbox 的shell 脚本,并让find 为每个相关目录运行该脚本。这是痕迹。 messages.tgz 文件包含“起点”目录结构的副本; reset 脚本删除更改的目录并从 tar 文件中恢复原始目录。我的提示是Osiris JL:

注意:我添加了-name 'm?' 条件以避免处理当前目录. 出现问题;你可能不需要那个。

使用doit-all-in-one

Osiris JL: reset
Osiris JL: ls -R
doit        doit-all-in-one fixmbox     m1          m2        messages.tgz    reset

./m1:
email-0.emlx email-2.emlx email-4.emlx email-6.emlx email-8.emlx
email-1.emlx email-3.emlx email-5.emlx email-7.emlx email-9.emlx

./m2:
email-0.emlx email-2.emlx email-4.emlx email-6.emlx email-8.emlx
email-1.emlx email-3.emlx email-5.emlx email-7.emlx email-9.emlx
Osiris JL: cat doit-all-in-one
set -x
path_to_folders=.
find "$path_to_folders" -name 'm?' -type d \
        -exec mv {} {}.mbox \; \
        -exec mkdir {}.mbox/Messages \; \
        -exec sh -c "mv {}.mbox/*.emlx {}.mbox/Messages" \;
Osiris JL: bash doit-all-in-one
+ path_to_folders=.
+ find . -name 'm?' -type d -exec mv '{}' '{}.mbox' ';' -exec mkdir '{}.mbox/Messages' ';' -exec sh -c 'mv {}.mbox/*.emlx {}.mbox/Messages' ';'
find: ./m1: No such file or directory
find: ./m2: No such file or directory
Osiris JL: ls -R
doit        doit-all-in-one fixmbox     m1.mbox     m2.mbox   messages.tgz    reset

./m1.mbox:
Messages

./m1.mbox/Messages:
email-0.emlx email-2.emlx email-4.emlx email-6.emlx email-8.emlx
email-1.emlx email-3.emlx email-5.emlx email-7.emlx email-9.emlx

./m2.mbox:
Messages

./m2.mbox/Messages:
email-0.emlx email-2.emlx email-4.emlx email-6.emlx email-8.emlx
email-1.emlx email-3.emlx email-5.emlx email-7.emlx email-9.emlx
Osiris JL: 

使用fixmbox:

Osiris JL: reset
Osiris JL: cat fixmbox
for dir in "$@"
do
    echo "$dir"
    mv "$dir" "$dir".mbox
    mkdir "$dir".mbox/Messages
    mv "$dir".mbox/*.emlx "$dir".mbox/Messages
done
Osiris JL: find . -name 'm?' -type d -exec ./fixmbox {} +
./m1
./m2
Osiris JL: ls -R
doit        doit-all-in-one fixmbox   m1.mbox   m2.mbox     messages.tgz    reset

./m1.mbox:
Messages

./m1.mbox/Messages:
email-0.emlx email-2.emlx email-4.emlx email-6.emlx email-8.emlx
email-1.emlx email-3.emlx email-5.emlx email-7.emlx email-9.emlx

./m2.mbox:
Messages

./m2.mbox/Messages:
email-0.emlx email-2.emlx email-4.emlx email-6.emlx email-8.emlx
email-1.emlx email-3.emlx email-5.emlx email-7.emlx email-9.emlx
Osiris JL: 

我更喜欢第二种,因为根本没有警告。注意+ 运算符对find 的使用使其行为类似于xargs。大多数时候,编写一个像fixmbox 这样的简单脚本,然后从find 使用它(而不是试图让find 跳过所有的障碍)对我来说似乎更简单。例如,fixmbox 脚本可以被简单地修改为不会失败,如果在它被指定使用的目录之一中已经有一个Messages 目录。当然,find 首先可以排除Messages 目录;那些不需要将他们的.emlx 文件移动到另一个级别的子目录中。请注意,fixmbox 非常小心,以确保即使目录名称中有空格等它也能正常工作;使用sh -c "..." 的版本也不是那么容易实现的。

.emlx 文件都是空的;文件大小不是这个问题的问题。)

【讨论】:

  • 我从未想过我可以用find -exec 调用脚本。这太酷了!感谢您的帮助。
【解决方案2】:

一种解决方法可能是将文件列表放入文件中,而不是交给 xargs。之后,您可以遍历它们并移动它们

find /path/to/folders/ -name \*.emlx -print0 > filelist
for f in $(cat filelist) ; do mv $f ./Messages/ ; done

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-08-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-11
    • 2013-02-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多