重命名部分目录名称?

3
下面的命令找到了以下目录。
$ find tmp/ -name "date=*" -type d
tmp/year=2022/month=05/date=27
tmp/year=2022/month=05/date=21
tmp/year=2022/month=05/date=29
tmp/year=2022/month=05/date=24
tmp/year=2022/month=05/date=31
tmp/year=2022/month=06/date=01
tmp/year=2022/month=06/date=02

我需要通过将date=替换为day=来重命名目录。

find tmp/ -name "date=*" -type d -exec rename s/date=/day=/g "{}" +;

然而,该命令并不重命名目录?

我需要在Python中实现它。


我很好奇:为什么不直接使用像 tmp/2022/06/02 这样的结构呢? - accdias
1
一个更加便携的等效命令是 ... -exec bash -c 'for f; do mv "$f" "${f//date=/day=}"; done' _ {} +,但这仍然依赖于 Bash,当然 Bash 是相当普遍但不是标准的。 (双斜杠 // 匹配你的 /g 标志,但对于这些示例来说似乎是多余的;它表示如果在单个文件名中有多个匹配项,则替换所有匹配项。) - tripleee
@accdias 这个命令可以正常工作('data=' 'day=')。但是,当我使用Python subprocess.run(['find', 'tmp/', '-name', '"date=*"', '-type', 'd', '-exec', 'rename', 'date=', 'day=', '"{}"', '+;'])运行它后,它就不起作用了? - ca9163d9
@triplee,确实。我只是在上面构建了op已经发布的内容。你的解决方案显然更好,更具可移植性。 - accdias
1
@ca9163d9,所以你不应该从我们那里省略那部分。在Python中,您有更好的选择,可以使用pathlib而无需调用shell。 - accdias
显示剩余3条评论
3个回答

4

rename 实用程序不是标准的Unix工具/实用程序的一部分,而是以不同的版本存在。

我建议使用 bashmv,并结合该 find 命令:

find tmp -name "date=*" -type d -exec bash -c '
   for f;do echo mv "$f" "${f/date=/day=}"; done' _ {} +

我在上述命令中添加了echo以供您测试。一旦确认输出无误,只需从上述命令中删除echo即可。


3
如果您仍然希望从Python中实现这个功能,那么子进程是不必要的。
import os

for curdir, dirs, files in os.walk("/tmp"):
    for dirname in dirs:
        if dirname.startswith("date="):
            new = dirname.replace("date=", "day=")
            os.rename(os.path.join(curdir, dirname), os.path.join(curdir, new))

3

如果您使用的是Python 3.4或更高版本,可以使用pathlib库:

from pathlib import Path

tmp = Path('tmp')

for o in tmp.rglob('date=*'):
    if o.is_dir():
        o.rename(o.with_name(o.name.replace('date', 'day')))

为了解决您在帖子评论中提到的问题,您可以检查目标目录是否已经存在,然后按照您想要的方式进行解决。代码示例如下:
```

为了解决你在帖子评论中提到的问题,你可以先检查目标目录是否已经存在,然后根据需要进行处理。代码如下:

```
from pathlib import Path

tmp = Path('tmp')

for o in tmp.rglob('date=*'):
    new_name = o.with_name(o.name.replace('date', 'day'))
    if o.is_dir():
        if new_name.exists():
            # Your logic to work around a directory
            # that already exists goes here
        else:
            o.rename(new_name)

上述代码只是一个初步的想法。需要进行大量改进才能使其更可靠。


有时候,例如 date=01\aaa.zipday=01/bbb.zip 都存在。代码会报错 FileExistsError: [Errno 17] File exists: 'tmp/year=2022/month=05/date=01' -> 'tmp/year=2022/month=05/day=01'。是否有一种方法可以跳过重命名并将文件移动到目标目录名称已存在的情况下? - ca9163d9
当然可以!您可以检查目标名称是否已存在。我会尝试在代码中加入该测试。 - accdias

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接